diff options
Diffstat (limited to 'sourcecodes/bnt-master/BNT/inference/static')
227 files changed, 12053 insertions, 0 deletions
diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Entries new file mode 100644 index 00000000..a4fbc6ee --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Entries @@ -0,0 +1,7 @@ +/belprop_fg_inf_engine.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// +/find_mpe.m/1.1.1.1/Thu Jun 20 00:02:12 2002// +/loopy_converged.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_params.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Repository new file mode 100644 index 00000000..7e75998c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@belprop_fg_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/belprop_fg_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/belprop_fg_inf_engine.m new file mode 100644 index 00000000..1945c3f2 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/belprop_fg_inf_engine.m @@ -0,0 +1,47 @@ +function engine = belprop_fg_inf_engine(fg, varargin) +% BELPROP_FG_INF_ENGINE Make a belief propagation inference engine for factor graphs +% engine = belprop_fg_inf_engine(factor_graph, ...) +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default in brackets] +% e.g., engine = belprop_inf_engine(fg, 'tol', 1e-2, 'max_iter', 10) +% +% max_iter - max. num. iterations [ 2*num_nodes ] +% momentum - weight assigned to old message in convex combination (useful for damping oscillations) [0] +% tol - tolerance used to assess convergence [1e-3] +% maximize - 1 means use max-product, 0 means use sum-product [0] +% +% This uses potential objects, like belprop_inf_engine, and hence is quite slow. + +engine = init_fields; +engine = class(engine, 'belprop_fg_inf_engine'); + +% set params to default values +N = length(fg.G); +engine.max_iter = 2*N; +engine.momentum = 0; +engine.tol = 1e-3; +engine.maximize = 0; + +% parse optional arguments +engine = set_params(engine, varargin); + +engine.fgraph = fg; + +% store results computed by enter_evidence here +engine.marginal_nodes = cell(1, fg.nvars); +engine.evidence = []; + + +%%%%%%%%%%%% + +function engine = init_fields() + +engine.fgraph = []; +engine.max_iter = []; +engine.momentum = []; +engine.tol = []; +engine.maximize = []; +engine.marginal_nodes = []; +engine.evidence = []; +engine.niter = []; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/enter_evidence.m new file mode 100644 index 00000000..e275e298 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/enter_evidence.m @@ -0,0 +1,126 @@ +function [engine, ll, niter] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Propagate evidence using belief propagation +% [engine, ll, niter] = enter_evidence(engine, evidence, ...) +% +% The log-likelihood is not computed; ll = 0. +% niter contains the number of iterations used +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default value in brackets] +% +% maximize - 1 means use max-product, 0 means use sum-product [0] +% +% e.g., engine = enter_evidence(engine, ev, 'maximize', 1) + +ll = 0; +maximize = 0; + +if nargin >= 3 + args = varargin; + nargs = length(args); + for i=1:2:nargs + switch args{i}, + case 'maximize', maximize = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + +verbose = 0; + +ns = engine.fgraph.node_sizes; +onodes = find(~isemptycell(evidence)); +hnodes = find(isemptycell(evidence)); +cnodes = engine.fgraph.cnodes; +pot_type = determine_pot_type(engine.fgraph, onodes); + +% prime each local kernel with evidence (if any) +nfactors = engine.fgraph.nfactors; +nvars = engine.fgraph.nvars; +factors = cell(1,nfactors); +for f=1:nfactors + K = engine.fgraph.factors{engine.fgraph.equiv_class(f)}; + factors{f} = convert_to_pot(K, pot_type, engine.fgraph.dom{f}(:), evidence); +end + +% initialise msgs +msg_var_to_fac = cell(nvars, nfactors); +for x=1:nvars + for f=engine.fgraph.dep{x} + msg_var_to_fac{x,f} = mk_initial_pot(pot_type, x, ns, cnodes, onodes); + end +end +msg_fac_to_var = cell(nfactors, nvars); +dom = cell(1, nfactors); +for f=1:nfactors + %hdom{f} = myintersect(engine.fgraph.dom{f}, hnodes); + dom{f} = engine.fgraph.dom{f}(:)'; + for x=dom{f} + msg_fac_to_var{f,x} = mk_initial_pot(pot_type, x, ns, cnodes, onodes); + %msg_fac_to_var{f,x} = marginalize_pot(factors{f}, x); + end +end + + + +converged = 0; +iter = 1; +var_prod = cell(1, nvars); +fac_prod = cell(1, nfactors); + +while ~converged && (iter <= engine.max_iter) + if verbose, fprintf('iter %d\n', iter); end + + % absorb + old_var_prod = var_prod; + for x=1:nvars + var_prod{x} = mk_initial_pot(pot_type, x, ns, cnodes, onodes); + for f=engine.fgraph.dep{x} + var_prod{x} = multiply_by_pot(var_prod{x}, msg_fac_to_var{f,x}); + end + end + for f=1:nfactors + fac_prod{f} = mk_initial_pot(pot_type, dom{f}, ns, cnodes, onodes); + for x=dom{f} + fac_prod{f} = multiply_by_pot(fac_prod{f}, msg_var_to_fac{x,f}); + end + end + + % send msgs to neighbors + old_msg_var_to_fac = msg_var_to_fac; + old_msg_fac_to_var = msg_fac_to_var; + converged = 1; + for x=1:nvars + %if verbose, disp(['var ' num2str(x) ' sending to fac ' num2str(engine.fgraph.dep{x})]); end + for f=engine.fgraph.dep{x} + temp = divide_by_pot(var_prod{x}, old_msg_fac_to_var{f,x}); + msg_var_to_fac{x,f} = normalize_pot(temp); + if ~approxeq_pot(msg_var_to_fac{x,f}, old_msg_var_to_fac{x,f}, engine.tol), converged = 0; end + end + end + for f=1:nfactors + %if verbose, disp(['fac ' num2str(f) ' sending to var ' num2str(dom{f})]); end + for x=dom{f} + temp = divide_by_pot(fac_prod{f}, old_msg_var_to_fac{x,f}); + temp2 = multiply_by_pot(factors{f}, temp); + temp3 = marginalize_pot(temp2, x, maximize); + msg_fac_to_var{f,x} = normalize_pot(temp3); + if ~approxeq_pot(msg_fac_to_var{f,x}, old_msg_fac_to_var{f,x}, engine.tol), converged = 0; end + end + end + + if iter==1 + converged = 0; + end + iter = iter + 1; +end + +niter = iter - 1; +engine.niter = niter; + +for x=1:nvars + engine.marginal_nodes{x} = normalize_pot(var_prod{x}); +end + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/find_mpe.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/find_mpe.m new file mode 100644 index 00000000..439936d5 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/find_mpe.m @@ -0,0 +1,49 @@ +function mpe = find_mpe(engine, evidence, varargin) +% FIND_MPE Find the most probable explanation of the data (belprop_fg) +% function mpe = find_mpe(engine, evidence,...) +% +% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector). +% +% This finds the marginally most likely value for each hidden node, +% and may give the wrong results even if the graph is acyclic, +% unless you set break_ties = 1. +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default value in brackets] +% +% break_ties is optional. If 1, we will force ties to be broken consistently +% by calling enter_evidence N times. (see Jensen96, p106) Default = 1. + +break_ties = 1; + +% parse optional params +args = varargin; +nargs = length(args); +for i=1:2:nargs + switch args{i}, + case 'break_ties', break_ties = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end +end + +engine = enter_evidence(engine, evidence, 'maximize', 1); + +observed = ~isemptycell(evidence); +evidence = evidence(:); % hack to handle unrolled DBNs +N = length(evidence); +mpe = cell(1,N); +for i=1:N + m = marginal_nodes(engine, i); + % observed nodes are all set to 1 inside the inference engine, so we must undo this + if observed(i) + mpe{i} = evidence{i}; + else + mpe{i} = argmax(m.T); + if break_ties + evidence{i} = mpe{i}; + [engine, ll] = enter_evidence(engine, evidence, 'maximize', 1); + end + end +end + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/loopy_converged.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/loopy_converged.m new file mode 100644 index 00000000..b9015e85 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/loopy_converged.m @@ -0,0 +1,12 @@ +function niter = loopy_converged(engine) +% LOOPY_CONVERGED Did loopy belief propagation converge? 0 means no, eles we return the num. iterations. +% function niter = loopy_converged(engine) +% +% We use a simple heuristic: we say convergence occurred if the number of iterations +% used was less than the maximum allowed. + +if engine.niter == engine.max_iter + niter = 0; +else + niter = engine.niter; +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..0c85aed6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/marginal_nodes.m @@ -0,0 +1,6 @@ +function marginal = marginal_nodes(engine, query) +% MARGINAL_NODES Compute the marginal on the specified query nodes (belprop) +% marginal = marginal_nodes(engine, query) + +assert(length(query)==1); +marginal = pot_to_marginal(engine.marginal_nodes{query}); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/set_params.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/set_params.m new file mode 100644 index 00000000..a495b3bb --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/set_params.m @@ -0,0 +1,24 @@ +function engine = set_params(engine, varargin) +% SET_PARAMS Set the parameters (fields) for a belprop_inf_engine object +% engine = set_params(engine, name/value pairs) +% +% The following optional arguments can be specified in the form of name/value pairs: +% e.g., engine = set_params(engine, 'tol', 1e-2, 'max_iter', 10) +% +% max_iter - max. num. loopy iterations +% momentum - weight assigned to old message in convex combination +% tol - tolerance used to assess convergence +% maximize - 1 means use max-product, 0 means use sum-product + +args = varargin{1}; +nargs = length(args); +for i=1:2:nargs + switch args{i}, + case 'max_iter', engine.max_iter = args{i+1}; + case 'momentum', engine.momentum = args{i+1}; + case 'tol', engine.tol = args{i+1}; + case 'maximize', engine.maximize = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Entries new file mode 100644 index 00000000..b2150de3 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Entries @@ -0,0 +1,7 @@ +/belprop_inf_engine.m/1.1.1.1/Tue Dec 31 19:00:06 2002// +/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/find_mpe.m/1.1.1.1/Wed Jun 19 22:08:40 2002// +/loopy_converged.m/1.1.1.1/Wed May 29 15:59:56 2002// +/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// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Entries.Log b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Entries.Log new file mode 100644 index 00000000..9c6f22e4 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Entries.Log @@ -0,0 +1,2 @@ +A D/Old//// +A D/private//// diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Repository new file mode 100644 index 00000000..928be328 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@belprop_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/CVS/Entries new file mode 100644 index 00000000..06598b7b --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/CVS/Entries @@ -0,0 +1,6 @@ +/belprop_gdl_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002// +/belprop_inf_engine_nostr.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_evidence1.m/1.1.1.1/Wed May 29 15:59:56 2002// +/marginal_domain.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/CVS/Repository new file mode 100644 index 00000000..f6b12595 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@belprop_inf_engine/Old diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_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/@belprop_inf_engine/Old/belprop_gdl_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/belprop_gdl_inf_engine.m new file mode 100644 index 00000000..f3b84925 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/belprop_gdl_inf_engine.m @@ -0,0 +1,67 @@ +function engine = belprop_gdl_inf_engine(gdl, varargin) +% BELPROP_GDL_INF_ENGINE Make a belief propagation inference engine for a GDL graph +% engine = belprop_gdl_inf_engine(gdl_graph, ...) +% +% If the GDL graph is a tree, this will give exact results. +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default in brackets] +% e.g., engine = belprop_inf_engine(gdl, 'tol', 1e-2, 'max_iter', 10) +% +% protocol - 'tree' means send messages up then down the tree, +% 'parallel' means use synchronous updates ['parallel'] +% max_iter - max. num. iterations [ 2*num_nodes ] +% momentum - weight assigned to old message in convex combination (useful for damping oscillations) [0] +% tol - tolerance used to assess convergence [1e-3] +% maximize - 1 means use max-product, 0 means use sum-product [0] + + +engine = init_fields; +engine = class(engine, 'belprop_gdl_inf_engine'); + +% set default params +N = length(gdl.G); +engine.protocol = 'parallel'; +engine.max_iter = 2*N; +engine.momentum = 0; +engine.tol = 1e-3; +engine.maximize = 0; + +engine = set_params(engine, varargin); + +engine.gdl = gdl; + +if strcmp(engine.protocol, 'tree') + % Make a rooted tree, so there is a fixed message passing order. + root = N; + [engine.tree, engine.preorder, engine.postorder, height, cyclic] = mk_rooted_tree(gdl.G, root); + assert(~cyclic); +end + +% store results computed by enter_evidence here +ndoms = length(gdl.doms); +nvars = length(gdl.vars); +engine.marginal_domains = cell(1, ndoms); + +% to compute the marginal on each variable, we need to know which domain to marginalize +% and we want to choose the lightest. We compute the weight once we have seen the evidence. +engine.dom_weight = []; +engine.evidence = []; + + +%%%%%%%%% + +function engine = init_fields() + +engine.protocol = []; +engine.gdl = []; +engine.max_iter = []; +engine.momentum = []; +engine.tol = []; +engine.maximize = []; +engine.marginal_domains = []; +engine.evidence = []; +engine.tree = []; +engine.preorder = []; +engine.postorder = []; +engine.dom_weight = []; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/belprop_inf_engine_nostr.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/belprop_inf_engine_nostr.m new file mode 100644 index 00000000..8219a868 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/belprop_inf_engine_nostr.m @@ -0,0 +1,31 @@ +function engine = belprop_inf_engine(fg, max_iter, momentum, tol, maximize) + +if nargin < 2, max_iter = length(fg.G); end +if nargin < 3, momentum = 0; end +if nargin < 4, tol = 1e-3; end +if nargin < 5, maximize = 0; end + +engine.fgraph = fg; +engine.max_iter = max_iter; +engine.momentum = momentum; +engine.tol = tol; +engine.maximize = maximize; + +% store results computed by enter_evidence here +ndoms = length(fg.doms); +nvars = length(fg.vars); +engine.marginal_domains = cell(1, ndoms); + +% to compute the marginal on each variable, we need to know which domain to marginalize +% so we represent each domain as a bit vector, and compute its (pre-evidence) weight +engine.dom_weight = []; + +% engine.dom_bitv = sparse(ndoms, nvars); +% ns = fg.node_sizes; +% for i=1:ndoms +% engine.dom_bitv(i, fg.doms{i}) = 1; +% engine.dom_weight(i) = prod(ns(fg.doms{i})); +% end + + +engine = class(engine, 'belprop_inf_engine'); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/enter_evidence.m new file mode 100644 index 00000000..54649557 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/enter_evidence.m @@ -0,0 +1,80 @@ +function engine = enter_evidence(engine, evidence) + +doms = engine.fg.doms; +ndoms = length(doms); +ns = engine.fg.node_sizes; +obs = find(~isemptycell(evidence)); +cobs = myintersect(obs, engine.fg.cnodes); +dobs = myintersect(obs, engine.fg.dnodes); +ns(cobs) = 0; +ns(dobs) = 1; + +% prime each local kernel with evidence (if any) +local_kernel = cell(1, ndoms); +for i=1:length(engine.fg.kernels_of_type) + u = engine.fg.kernels_of_type{i}; + local_kernel(u) = kernel_to_dpots(engine.fg.kernels{i}, evidence, engine.fg.domains_of_type{i}); +end + +% initialise all msgs to 1s +nedges = engine.fg.nedges; +msg = cell(1, nedges); +for i=1:nedges + msg{i} = dpot(engine.fg.sepset{i}, ns(engine.fg.sepset{i})); +end + +prod_of_msg = cell(1, ndoms); +bel = cell(1, ndoms); +old_bel = cell(1, ndoms); + +converged = 0; +iter = 1; +while ~converged & (iter <= engine.max_iter) + + % each node multiplies all its incoming msgs + for i=1:ndoms + prod_of_msg{i} = dpot(doms{i}, ns(doms{i})); + nbrs = engine.fg.nbrs{i}; + for j=1:length(nbrs) + ndx = engine.fg.edge_ndx(j,i); + prod_of_msg{i} = multiply_by_pot(prod_of_msg{i}, msg{ndx}); + end + end + old_msg = msg; + + % each node computes its local belief + for i=1:ndoms + bel{i} = normalize_pot(multiply_pots(prod_of_msg{i}, local_kernel{i})); + end + + % converged? + converged = 1; + for i=1:ndoms + if ~approxeq(bel{i}, old_bel{i}, engine.tol) + converged = 0; + break; + end + end + + if ~converged + % each node sends a msg to each of its neighbors + for i=1:ndoms + nbrs = engine.fg.nbrs{i}; + for j=1:length(nbrs) + % multiply all incoming msgs except from j + temp = prod_of_msg{i}; + ndx = engine.fg.edge_ndx(j,i); + temp = divide_by_pot(temp, old_msg{ndx}); + % send msg from i to j + temp = multiply_by_pot(temp, local_kernel{i}); + ndx = engine.fg.edge_ndx(i,j); + msg{ndx} = normalize_pot(marginalize_pot(temp, engine.fg.sepset{ndx})); + end + end + end + + iter = iter + 1; +end + + +engine.marginal = bel; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/enter_evidence1.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/enter_evidence1.m new file mode 100644 index 00000000..b38cd3cb --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/enter_evidence1.m @@ -0,0 +1,94 @@ +function engine = enter_evidence(engine, evidence) + +doms = engine.fgraph.doms; +ndoms = length(doms); +ns = engine.fgraph.node_sizes; +obs = find(~isemptycell(evidence)); +cobs = myintersect(obs, engine.fgraph.cnodes); +dobs = myintersect(obs, engine.fgraph.dnodes); +ns(cobs) = 0; +ns(dobs) = 1; + +% recompute the weight of each domain now that we know what nodes are observed +for i=1:ndoms + engine.dom_weight(i) = prod(ns(engine.fgraph.doms{i})); +end + +% prime each local kernel with evidence (if any) +local_kernel = cell(1, ndoms); +for i=1:length(engine.fgraph.kernels_of_type) + u = engine.fgraph.kernels_of_type{i}; + local_kernel(u) = kernel_to_dpots(engine.fgraph.kernels{i}, evidence, engine.fgraph.domains_of_type{i}); +end + +% initialise all msgs to 1s +msg = cell(ndoms, ndoms); +for i=1:ndoms + nbrs = engine.fgraph.nbrs{i}; + for j=nbrs(:)' + dom = engine.fgraph.sepset{i,j}; + msg{i,j} = dpot(dom, ns(dom)); + end +end + +prod_of_msg = cell(1, ndoms); +bel = cell(1, ndoms); +old_bel = cell(1, ndoms); + +converged = 0; +iter = 1; +while ~converged & (iter <= engine.max_iter) + + % each node multiplies all its incoming msgs + for i=1:ndoms + prod_of_msg{i} = dpot(doms{i}, ns(doms{i})); + nbrs = engine.fgraph.nbrs{i}; + for j=nbrs(:)' + prod_of_msg{i} = multiply_by_pot(prod_of_msg{i}, msg{j,i}); + end + end + + % each node computes its local belief + old_bel = bel; + for i=1:ndoms + bel{i} = normalize_pot(multiply_pots(prod_of_msg{i}, local_kernel{i})); + end + + % converged? + if iter==1 + converged = 0; + else + converged = 1; + for i=1:ndoms + belT = get_params(bel{i}, 'table'); + old_belT = get_params(old_bel{i}, 'table'); + if ~approxeq(belT, old_belT, engine.tol) + converged = 0; + break; + end + end + end + + if ~converged + old_msg = msg; + % each node sends a msg to each of its neighbors + for i=1:ndoms + nbrs = engine.fgraph.nbrs{i}; + for j=nbrs(:)' + % multiply all incoming msgs except from j + temp = prod_of_msg{i}; + temp = divide_by_pot(temp, old_msg{j,i}); + % send msg from i to j + temp = multiply_by_pot(temp, local_kernel{i}); + msg{i,j} = normalize_pot(marginalize_pot(temp, engine.fgraph.sepset{i,j})); + end + end + end + + iter = iter + 1 +end + +engine.marginal_domains = bel; +%for i=1:ndoms + %engine.marginal_domains{i} = get_params(bel{i}, 'table'); +%end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/marginal_domain.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/marginal_domain.m new file mode 100644 index 00000000..49ad94c5 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/Old/marginal_domain.m @@ -0,0 +1,5 @@ +function marginal = marginal_domain(engine, i) +% MARGINAL_DOMAIN Return the marginal on the specified domain (belprop) +% marginal = marginal_domain(engine, i) + +marginal = pot_to_marginal(engine.marginal_domains{i}); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/belprop_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/belprop_inf_engine.m new file mode 100644 index 00000000..839af506 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/belprop_inf_engine.m @@ -0,0 +1,90 @@ +function engine = belprop_inf_engine(bnet, varargin) +% BELPROP_INF_ENGINE Make a loopy belief propagation inference engine +% engine = belprop_inf_engine(bnet, ...) +% +% This is like pearl_inf_engine, except it uses potential objects, +% instead of lambda/pi structs. Hence it is slower. +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default in brackets] +% +% protocol - 'tree' means send messages up then down the tree, +% 'parallel' means use synchronous updates ['parallel'] +% max_iter - max. num. iterations [ 2*num_nodes ] +% momentum - weight assigned to old message in convex combination (useful for damping oscillations) [0] +% tol - tolerance used to assess convergence [1e-3] +% maximize - 1 means use max-product, 0 means use sum-product [0] +% filename - name of file to write beliefs to after each iteration within enter_evidence [ [] ] +% +% e.g., engine = belprop_inf_engine(bnet, 'maximize', 1, 'max_iter', 10) + +% gdl = general distributive law +engine.gdl = bnet_to_gdl(bnet); + +% set default params +N = length(engine.gdl.G); +engine.protocol = 'parallel'; +engine.max_iter = 2*N; +engine.momentum = 0; +engine.tol = 1e-3; +engine.maximize = 0; +engine.filename = []; +engine.fid = []; + +args = varargin; +nargs = length(args); +for i=1:2:nargs + switch args{i}, + case 'max_iter', engine.max_iter = args{i+1}; + case 'momentum', engine.momentum = args{i+1}; + case 'tol', engine.tol = args{i+1}; + case 'protocol', engine.protocol = args{i+1}; + case 'filename', engine.filename = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end +end + + +if strcmp(engine.protocol, 'tree') + % Make a rooted tree, so there is a fixed message passing order. + root = N; + [engine.tree, engine.preorder, engine.postorder, height, cyclic] = mk_rooted_tree(engine.gdl.G, root); + assert(~cyclic); +end + +% store results computed by enter_evidence here +engine.marginal_domains = cell(1, N); + +engine.niter = []; + +engine = class(engine, 'belprop_inf_engine', inf_engine(bnet)); + +%%%%%%%%% + +function gdl = bnet_to_gdl(bnet) + +gdl.G = mk_undirected(bnet.dag); +N = length(bnet.dag); +gdl.doms = cell(1,N); +for i=1:N + gdl.doms{i} = family(bnet.dag, i); +end + +% Compute a bit vector representation of the set of domains +% dom_bitv(i,j) = 1 iff variable j occurs in domain i +gdl.dom_bitv = zeros(N, N); +for i=1:N + gdl.dom_bitv(i, gdl.doms{i}) = 1; +end + +% compute the interesection of the domains on either side of each edge (separating set) +gdl.sepset = cell(N, N); +gdl.nbrs = cell(1,N); +for i=1:N + nbrs = neighbors(gdl.G, i); + gdl.nbrs{i} = nbrs; + for j = nbrs(:)' + gdl.sepset{i,j} = myintersect(gdl.doms{i}, gdl.doms{j}); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/enter_evidence.m new file mode 100644 index 00000000..88cce18e --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/enter_evidence.m @@ -0,0 +1,86 @@ +function [engine, ll, niter] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Propagate evidence using belief propagation +% [engine, ll, niter] = enter_evidence(engine, evidence, ...) +% +% The log-likelihood is not computed; ll = 0. +% niter contains the number of iterations used (if engine.protocol = 'parallel') +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default value in brackets] +% +% maximize - 1 means use max-product, 0 means use sum-product [0] +% exclude - list of nodes whose potential will not be included in the joint [ [] ] +% +% e.g., engine = enter_evidence(engine, ev, 'maximize', 1) + +ll = 0; +exclude = []; +maximize = 0; + +if nargin >= 3 + args = varargin; + nargs = length(args); + for i=1:2:nargs + switch args{i}, + case 'exclude', exclude = args{i+1}; + case 'maximize', maximize = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + +engine.maximize = maximize; + +if ~isempty(engine.filename) + engine.fid = fopen(engine.filename, 'w'); + if engine.fid == 0 + error(['can''t open ' engine.filename]); + end +else + engine.fid = []; +end + +gdl = engine.gdl; +bnet = bnet_from_engine(engine); + +ndoms = length(gdl.doms); +ns = bnet.node_sizes; +onodes = find(~isemptycell(evidence)); +pot_type = determine_pot_type(bnet, onodes); + +% prime each local kernel with evidence (if any) +local_kernel = cell(1, ndoms); +for i=1:ndoms + if myismember(i, exclude) + local_kernel{i} = mk_initial_pot(pot_type, gdl.doms{i}, ns, bnet.cnodes, onodes); + else + e = bnet.equiv_class(i); + local_kernel{i} = convert_to_pot(bnet.CPD{e}, pot_type, gdl.doms{i}(:), evidence); + end +end + +% initialise all msgs to 1s +msg = cell(ndoms, ndoms); +for i=1:ndoms + nbrs = gdl.nbrs{i}; + for j=nbrs(:)' + dom = gdl.sepset{i,j}; + msg{i,j} = mk_initial_pot(pot_type, dom, ns, bnet.cnodes, onodes); + end +end + +switch engine.protocol + case 'parallel', + [engine.marginal_domains, niter] = parallel_protocol(engine, evidence, pot_type, local_kernel, msg); + case 'tree', + engine.marginal_domains = serial_protocol(engine, evidence, pot_type, local_kernel, msg); + niter = 1; +end +engine.niter = niter; + +%fprintf('just finished %d iterations of belprop\n', niter); + +if ~isempty(engine.filename) + fclose(engine.fid); +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/find_mpe.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/find_mpe.m new file mode 100644 index 00000000..73bd0abc --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/find_mpe.m @@ -0,0 +1,49 @@ +function mpe = find_mpe(engine, evidence, varargin) +% FIND_MPE Find the most probable explanation of the data (belprop) +% function mpe = find_mpe(engine, evidence,...) +% +% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector). +% +% This finds the marginally most likely value for each hidden node, +% and may give the wrong results even if the graph is acyclic, +% unless you set break_ties = 1. +% +% The following optional arguments can be specified in the form of name/value pairs: +% [default value in brackets] +% +% break_ties is optional. If 1, we will force ties to be broken consistently +% by calling enter_evidence N times. (see Jensen96, p106) Default = 1. + +break_ties = 1; + +% parse optional params +args = varargin; +nargs = length(args); +for i=1:2:nargs + switch args{i}, + case 'break_ties', break_ties = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end +end + +engine = enter_evidence(engine, evidence, 'maximize', 1); + +observed = ~isemptycell(evidence); +evidence = evidence(:); % hack to handle unrolled DBNs +N = length(evidence); +mpe = cell(1,N); +for i=1:N + m = marginal_nodes(engine, i); + % observed nodes are all set to 1 inside the inference engine, so we must undo this + if observed(i) + mpe{i} = evidence{i}; + else + mpe{i} = argmax(m.T); + if break_ties + evidence{i} = mpe{i}; + [engine, ll] = enter_evidence(engine, evidence, 'maximize', 1); + end + end +end + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/loopy_converged.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/loopy_converged.m new file mode 100644 index 00000000..fba4f2fd --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/loopy_converged.m @@ -0,0 +1,13 @@ +function niter = loopy_converged(engine) +% LOOPY_CONVERGED Did loopy belief propagation converge? 0 means no, eles we return the num. iterations. +% function niter = loopy_converged(engine) +% +% We use a simple heuristic: we say convergence occurred if the number of iterations +% used was less than the maximum allowed. + +if engine.niter == engine.max_iter + niter = 0; +else + niter = engine.niter; +end +%conv = (strcmp(engine.protocol, 'tree') | (engine.niter < engine.max_iter)); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/marginal_family.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/marginal_family.m new file mode 100644 index 00000000..afe404a8 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/marginal_family.m @@ -0,0 +1,6 @@ +function [marginal, pot] = marginal_family(engine, query) +% MARGINAL_NODES Compute the marginal on the family of the specified query node (belprop) +% [marginal, pot] = marginal_family(engine, query) + +pot = engine.marginal_domains{query}; +marginal = pot_to_marginal(pot); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..0c2b5d94 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/marginal_nodes.m @@ -0,0 +1,14 @@ +function [marginal, pot] = marginal_nodes(engine, query) +% MARGINAL_NODES Compute the marginal on the specified query nodes (belprop) +% [marginal, pot] = marginal_nodes(engine, query) +% +% query must be a subset of a family + +if isempty(query) + big_pot = engine.marginal_domains{1}; % pick an arbitrary domain +else + big_pot = engine.marginal_domains{query(end)}; +end +pot = marginalize_pot(big_pot, query); +marginal = pot_to_marginal(pot); + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/CVS/Entries new file mode 100644 index 00000000..938d9867 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/CVS/Entries @@ -0,0 +1,4 @@ +/junk/1.1.1.1/Wed May 29 15:59:56 2002// +/parallel_protocol.m/1.1.1.1/Wed May 29 15:59:56 2002// +/tree_protocol.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/CVS/Repository new file mode 100644 index 00000000..9681913e --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@belprop_inf_engine/private diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/junk b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/junk new file mode 100644 index 00000000..11438db0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/junk @@ -0,0 +1,68 @@ +fgraph +fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph +fgraph +fgraphffgraphufgraphnfgraphcfgraphtfgraphifgraphofgraphnfgraph fgraph[fgraphbfgraphefgraphlfgraph,fgraph fgraphifgraphtfgraphefgraphrfgraph]fgraph fgraph=fgraph fgraphpfgraphafgraphrfgraphafgraphlfgraphlfgraphefgraphlfgraph_fgraphpfgraphrfgraphofgraphtfgraphofgraphcfgraphofgraphlfgraph(fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph,fgraph fgraphefgraphvfgraphifgraphdfgraphefgraphnfgraphcfgraphefgraph,fgraph fgraphpfgraphofgraphtfgraph_fgraphtfgraphyfgraphpfgraphefgraph,fgraph fgraphlfgraphofgraphcfgraphafgraphlfgraph_fgraphkfgraphefgraphrfgraphnfgraphefgraphlfgraph,fgraph fgraphmfgraphsfgraphgfgraph)fgraph +fgraph +fgraphdfgraphofgraphmfgraphsfgraph fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphdfgraphofgraphmfgraphsfgraph;fgraph +fgraphnfgraphdfgraphofgraphmfgraphsfgraph fgraph=fgraph fgraphlfgraphefgraphnfgraphgfgraphtfgraphhfgraph(fgraphdfgraphofgraphmfgraphsfgraph)fgraph;fgraph +fgraphnfgraphsfgraph fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphnfgraphofgraphdfgraphefgraph_fgraphsfgraphifgraphzfgraphefgraphsfgraph;fgraph +fgraphofgraphnfgraphofgraphdfgraphefgraphsfgraph fgraph=fgraph fgraphffgraphifgraphnfgraphdfgraph(fgraph~fgraphifgraphsfgraphefgraphmfgraphpfgraphtfgraphyfgraphcfgraphefgraphlfgraphlfgraph(fgraphefgraphvfgraphifgraphdfgraphefgraphnfgraphcfgraphefgraph)fgraph)fgraph;fgraph +fgraphcfgraphnfgraphofgraphdfgraphefgraphsfgraph fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphcfgraphnfgraphofgraphdfgraphefgraphsfgraph;fgraph +fgraph +fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph fgraph=fgraph fgraphcfgraphefgraphlfgraphlfgraph(fgraph1fgraph,fgraph fgraphnfgraphdfgraphofgraphmfgraphsfgraph)fgraph;fgraph +fgraphbfgraphefgraphlfgraph fgraph=fgraph fgraphcfgraphefgraphlfgraphlfgraph(fgraph1fgraph,fgraph fgraphnfgraphdfgraphofgraphmfgraphsfgraph)fgraph;fgraph +fgraphofgraphlfgraphdfgraph_fgraphbfgraphefgraphlfgraph fgraph=fgraph fgraphcfgraphefgraphlfgraphlfgraph(fgraph1fgraph,fgraph fgraphnfgraphdfgraphofgraphmfgraphsfgraph)fgraph;fgraph +fgraph +fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph fgraph=fgraph fgraph0fgraph;fgraph +fgraphifgraphtfgraphefgraphrfgraph fgraph=fgraph fgraph1fgraph;fgraph +fgraphwfgraphhfgraphifgraphlfgraphefgraph fgraph~fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph fgraph&fgraph fgraph(fgraphifgraphtfgraphefgraphrfgraph fgraph<fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphmfgraphafgraphxfgraph_fgraphifgraphtfgraphefgraphrfgraph)fgraph +fgraph fgraph fgraph +fgraph fgraph fgraph%fgraph fgraphefgraphafgraphcfgraphhfgraph fgraphnfgraphofgraphdfgraphefgraph fgraphmfgraphufgraphlfgraphtfgraphifgraphpfgraphlfgraphifgraphefgraphsfgraph fgraphafgraphlfgraphlfgraph fgraphifgraphtfgraphsfgraph fgraphifgraphnfgraphcfgraphofgraphmfgraphifgraphnfgraphgfgraph fgraphmfgraphsfgraphgfgraphsfgraph fgraphafgraphnfgraphdfgraph fgraphcfgraphofgraphmfgraphpfgraphufgraphtfgraphefgraphsfgraph fgraphifgraphtfgraphsfgraph fgraphlfgraphofgraphcfgraphafgraphlfgraph fgraphbfgraphefgraphlfgraphifgraphefgraphffgraph +fgraph fgraph fgraphofgraphlfgraphdfgraph_fgraphbfgraphefgraphlfgraph fgraph=fgraph fgraphbfgraphefgraphlfgraph;fgraph +fgraph fgraph fgraphffgraphofgraphrfgraph fgraphifgraph=fgraph1fgraph:fgraphnfgraphdfgraphofgraphmfgraphsfgraph +fgraph fgraph fgraph fgraph fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph{fgraphifgraph}fgraph fgraph=fgraph fgraphmfgraphkfgraph_fgraphifgraphnfgraphifgraphtfgraphifgraphafgraphlfgraph_fgraphpfgraphofgraphtfgraph(fgraphpfgraphofgraphtfgraph_fgraphtfgraphyfgraphpfgraphefgraph,fgraph fgraphdfgraphofgraphmfgraphsfgraph{fgraphifgraph}fgraph,fgraph fgraphnfgraphsfgraph,fgraph fgraphcfgraphnfgraphofgraphdfgraphefgraphsfgraph,fgraph fgraphofgraphnfgraphofgraphdfgraphefgraphsfgraph)fgraph;fgraph +fgraph fgraph fgraph fgraph fgraphnfgraphbfgraphrfgraphsfgraph fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphnfgraphbfgraphrfgraphsfgraph{fgraphifgraph}fgraph;fgraph +fgraph fgraph fgraph fgraph fgraphffgraphofgraphrfgraph fgraphjfgraph=fgraphnfgraphbfgraphrfgraphsfgraph(fgraph:fgraph)fgraph'fgraph +fgraph fgraph fgraph fgraph fgraph fgraph fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph{fgraphifgraph}fgraph fgraph=fgraph fgraphmfgraphufgraphlfgraphtfgraphifgraphpfgraphlfgraphyfgraph_fgraphbfgraphyfgraph_fgraphpfgraphofgraphtfgraph(fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph{fgraphifgraph}fgraph,fgraph fgraphmfgraphsfgraphgfgraph{fgraphjfgraph,fgraphifgraph}fgraph)fgraph;fgraph +fgraph fgraph fgraph fgraph fgraphefgraphnfgraphdfgraph +fgraph fgraph fgraph fgraph fgraphbfgraphefgraphlfgraph{fgraphifgraph}fgraph fgraph=fgraph fgraphnfgraphofgraphrfgraphmfgraphafgraphlfgraphifgraphzfgraphefgraph_fgraphpfgraphofgraphtfgraph(fgraphmfgraphufgraphlfgraphtfgraphifgraphpfgraphlfgraphyfgraph_fgraphpfgraphofgraphtfgraphsfgraph(fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph{fgraphifgraph}fgraph,fgraph fgraphlfgraphofgraphcfgraphafgraphlfgraph_fgraphkfgraphefgraphrfgraphnfgraphefgraphlfgraph{fgraphifgraph}fgraph)fgraph)fgraph;fgraph +fgraph fgraph fgraphefgraphnfgraphdfgraph +fgraph +fgraph fgraph fgraph%fgraph fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph?fgraph +fgraph fgraph fgraphifgraphffgraph fgraphifgraphtfgraphefgraphrfgraph=fgraph=fgraph1fgraph +fgraph fgraph fgraph fgraph fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph fgraph=fgraph fgraph0fgraph;fgraph +fgraph fgraph fgraphefgraphlfgraphsfgraphefgraph +fgraph fgraph fgraph fgraph fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph fgraph=fgraph fgraph1fgraph;fgraph +fgraph fgraph fgraph fgraph fgraphffgraphofgraphrfgraph fgraphifgraph=fgraph1fgraph:fgraphnfgraphdfgraphofgraphmfgraphsfgraph +fgraph fgraph fgraph fgraph fgraph fgraph fgraphifgraphffgraph fgraph~fgraphafgraphpfgraphpfgraphrfgraphofgraphxfgraphefgraphqfgraph_fgraphpfgraphofgraphtfgraph(fgraphbfgraphefgraphlfgraph{fgraphifgraph}fgraph,fgraph fgraphofgraphlfgraphdfgraph_fgraphbfgraphefgraphlfgraph{fgraphifgraph}fgraph,fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphtfgraphofgraphlfgraph)fgraph +fgraph fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph fgraph=fgraph fgraph0fgraph;fgraph +fgraph fgraphbfgraphrfgraphefgraphafgraphkfgraph;fgraph +fgraph fgraph fgraph fgraph fgraph fgraph fgraphefgraphnfgraphdfgraph +fgraph fgraph fgraph fgraph fgraphefgraphnfgraphdfgraph +fgraph fgraph fgraphefgraphnfgraphdfgraph +fgraph +fgraph fgraph fgraphifgraphffgraph fgraph~fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph +fgraph fgraph fgraph fgraph fgraphofgraphlfgraphdfgraph_fgraphmfgraphsfgraphgfgraph fgraph=fgraph fgraphmfgraphsfgraphgfgraph;fgraph +fgraph fgraph fgraph fgraph fgraph%fgraph fgraphefgraphafgraphcfgraphhfgraph fgraphnfgraphofgraphdfgraphefgraph fgraphsfgraphefgraphnfgraphdfgraphsfgraph fgraphafgraph fgraphmfgraphsfgraphgfgraph fgraphtfgraphofgraph fgraphefgraphafgraphcfgraphhfgraph fgraphofgraphffgraph fgraphifgraphtfgraphsfgraph fgraphnfgraphefgraphifgraphgfgraphhfgraphbfgraphofgraphrfgraphsfgraph +fgraph fgraph fgraph fgraph fgraphffgraphofgraphrfgraph fgraphifgraph=fgraph1fgraph:fgraphnfgraphdfgraphofgraphmfgraphsfgraph +fgraph fgraph fgraph fgraph fgraph fgraph fgraphnfgraphbfgraphrfgraphsfgraph fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphnfgraphbfgraphrfgraphsfgraph{fgraphifgraph}fgraph;fgraph +fgraph fgraph fgraph fgraph fgraph fgraph fgraphffgraphofgraphrfgraph fgraphjfgraph=fgraphnfgraphbfgraphrfgraphsfgraph(fgraph:fgraph)fgraph'fgraph +fgraph fgraph%fgraph fgraphmfgraphufgraphlfgraphtfgraphifgraphpfgraphlfgraphyfgraph fgraphafgraphlfgraphlfgraph fgraphifgraphnfgraphcfgraphofgraphmfgraphifgraphnfgraphgfgraph fgraphmfgraphsfgraphgfgraphsfgraph fgraphefgraphxfgraphcfgraphefgraphpfgraphtfgraph fgraphffgraphrfgraphofgraphmfgraph fgraphjfgraph +fgraph fgraphtfgraphefgraphmfgraphpfgraph fgraph=fgraph fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph{fgraphifgraph}fgraph;fgraph +fgraph fgraphtfgraphefgraphmfgraphpfgraph fgraph=fgraph fgraphdfgraphifgraphvfgraphifgraphdfgraphefgraph_fgraphbfgraphyfgraph_fgraphpfgraphofgraphtfgraph(fgraphtfgraphefgraphmfgraphpfgraph,fgraph fgraphofgraphlfgraphdfgraph_fgraphmfgraphsfgraphgfgraph{fgraphjfgraph,fgraphifgraph}fgraph)fgraph;fgraph +fgraph fgraph%fgraph fgraphsfgraphefgraphnfgraphdfgraph fgraphmfgraphsfgraphgfgraph fgraphffgraphrfgraphofgraphmfgraph fgraphifgraph fgraphtfgraphofgraph fgraphjfgraph +fgraph fgraphtfgraphefgraphmfgraphpfgraph fgraph=fgraph fgraphmfgraphufgraphlfgraphtfgraphifgraphpfgraphlfgraphyfgraph_fgraphbfgraphyfgraph_fgraphpfgraphofgraphtfgraph(fgraphtfgraphefgraphmfgraphpfgraph,fgraph fgraphlfgraphofgraphcfgraphafgraphlfgraph_fgraphkfgraphefgraphrfgraphnfgraphefgraphlfgraph{fgraphifgraph}fgraph)fgraph;fgraph +fgraph fgraphifgraphffgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphmfgraphafgraphxfgraphifgraphmfgraphifgraphzfgraphefgraph +fgraph fgraph fgraph fgraphtfgraphefgraphmfgraphpfgraph2fgraph fgraph=fgraph fgraphmfgraphafgraphrfgraphgfgraphifgraphnfgraphafgraphlfgraphifgraphzfgraphefgraph_fgraphpfgraphofgraphtfgraph_fgraphmfgraphafgraphxfgraph(fgraphtfgraphefgraphmfgraphpfgraph,fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphsfgraphefgraphpfgraphsfgraphefgraphtfgraph{fgraphifgraph,fgraphjfgraph}fgraph)fgraph;fgraph +fgraph fgraphefgraphlfgraphsfgraphefgraph +fgraph fgraph fgraph fgraphtfgraphefgraphmfgraphpfgraph2fgraph fgraph=fgraph fgraphmfgraphafgraphrfgraphgfgraphifgraphnfgraphafgraphlfgraphifgraphzfgraphefgraph_fgraphpfgraphofgraphtfgraph(fgraphtfgraphefgraphmfgraphpfgraph,fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphsfgraphefgraphpfgraphsfgraphefgraphtfgraph{fgraphifgraph,fgraphjfgraph}fgraph)fgraph;fgraph +fgraph fgraphefgraphnfgraphdfgraph +fgraph fgraphmfgraphsfgraphgfgraph{fgraphifgraph,fgraphjfgraph}fgraph fgraph=fgraph fgraphnfgraphofgraphrfgraphmfgraphafgraphlfgraphifgraphzfgraphefgraph_fgraphpfgraphofgraphtfgraph(fgraphtfgraphefgraphmfgraphpfgraph2fgraph)fgraph;fgraph +fgraph fgraph fgraph fgraph fgraph fgraph fgraphefgraphnfgraphdfgraph +fgraph fgraph fgraph fgraph fgraphefgraphnfgraphdfgraph +fgraph fgraph fgraphefgraphnfgraphdfgraph +fgraph +fgraph fgraph fgraphifgraphtfgraphefgraphrfgraph fgraph=fgraph fgraphifgraphtfgraphefgraphrfgraph fgraph+fgraph fgraph1fgraph;fgraph +fgraphefgraphnfgraphdfgraph +fgraph +gdl diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/parallel_protocol.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/parallel_protocol.m new file mode 100644 index 00000000..3e702f7b --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/parallel_protocol.m @@ -0,0 +1,86 @@ +function [bel, niter] = parallel_protocol(engine, evidence, pot_type, local_kernel, msg) + +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes; +onodes = find(~isemptycell(evidence)); + +ndoms = length(engine.gdl.doms); +prod_of_msg = cell(1, ndoms); +bel = cell(1, ndoms); +old_bel = cell(1, ndoms); + +converged = 0; +iter = 1; +while ~converged && (iter <= engine.max_iter) + + % each node multiplies all its incoming msgs and computes its local belief + old_bel = bel; + for i=1:ndoms + prod_of_msg{i} = mk_initial_pot(pot_type, engine.gdl.doms{i}, ns, bnet.cnodes, onodes); + nbrs = engine.gdl.nbrs{i}; + for j=nbrs(:)' + prod_of_msg{i} = multiply_by_pot(prod_of_msg{i}, msg{j,i}); + end + bel{i} = normalize_pot(multiply_by_pot(local_kernel{i}, prod_of_msg{i})); + end + + if ~isempty(engine.fid) + for i=1:ndoms + tmp = pot_to_marginal(bel{i}); + %fprintf(engine.fid, '%9.7f ', tmp.T(1)); + fprintf(engine.fid, '%9.7f ', tmp.U(1)); + end + %fprintf(engine.fid, ' U '); + %for i=1:ndoms + % tmp = pot_to_marginal(bel{i}); + % fprintf(engine.fid, '%9.7f ', tmp.U(1)); + %end + fprintf(engine.fid, '\n'); + end + + % converged? + if iter==1 + converged = 0; + else + converged = 1; + for i=1:ndoms + if ~approxeq_pot(bel{i}, old_bel{i}, engine.tol) + converged = 0; + break; + end + end + end + + if ~converged + old_msg = msg; + % each node sends a msg to each of its neighbors + for i=1:ndoms + nbrs = engine.gdl.nbrs{i}; + for j=nbrs(:)' + % multiply all incoming msgs except from j + temp = prod_of_msg{i}; + temp = divide_by_pot(temp, old_msg{j,i}); + % send msg from i to j + temp = multiply_by_pot(temp, local_kernel{i}); + temp2 = marginalize_pot(temp, engine.gdl.sepset{i,j}, engine.maximize); + msg{i,j} = normalize_pot(temp2); + end + end + end + + iter = iter + 1; +end + + +niter = iter-1; + +if 0 +for i=1:ndoms + prod_of_msg{i} = mk_initial_pot(pot_type, engine.gdl.doms{i}, ns, bnet.cnodes, onodes); + nbrs = engine.gdl.nbrs{i}; + for j=nbrs(:)' + prod_of_msg{i} = multiply_by_pot(prod_of_msg{i}, msg{j,i}); + end + bel{i} = normalize_pot(multiply_by_pot(local_kernel{i}, prod_of_msg{i})); +end +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/tree_protocol.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/tree_protocol.m new file mode 100644 index 00000000..940e74ae --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_inf_engine/private/tree_protocol.m @@ -0,0 +1,48 @@ +function bel = tree_protocol(engine, evidence, pot_type, local_kernel, msg) + +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes; +onodes = find(~isemptycell(evidence)); + +ndoms = length(engine.gdl.doms); +prod_of_msg = cell(1, ndoms); +bel = cell(1, ndoms); + +% collect to root (node to parents) +for n=engine.postorder + % absorb msgs from children + prod_of_msg{n} = mk_initial_pot(pot_type, engine.gdl.doms{n}, ns, bnet.cnodes, onodes); + for c=children(engine.tree, n) + prod_of_msg{n} = multiply_by_pot(prod_of_msg{n}, msg{c,n}); + end + % send msg to parents + for p=parents(engine.tree, n) + if iter==1 + temp = prod_of_msg{n}; + else + temp = divide_by_pot(prod_of_msg{n}, old_msg{p,n}); + end + temp = multiply_by_pot(temp, local_kernel{n}); + temp2 = marginalize_pot(temp, engine.gdl.sepset{n,p}, engine.maximize); + %fprintf('%d sends %d\n', n, p); + msg{n,p} = normalize_pot(temp2); + end +end + +% distribute from root (node to children) +for n=engine.preorder + % absorb from parents + %prod_of_msg{n} = mk_initial_pot(pot_type, doms{n}, ns, cnodes, onodes); + for p=parents(engine.tree, n) + prod_of_msg{n} = multiply_by_pot(prod_of_msg{n}, msg{p,n}); + end + bel{n} = normalize_pot(multiply_pots(prod_of_msg{n}, local_kernel{n})); + % send msg to children + for c=children(engine.tree, n) + temp = divide_by_pot(prod_of_msg{n}, msg{c,n}); + temp = multiply_by_pot(temp, local_kernel{n}); + temp2 = marginalize_pot(temp, engine.gdl.sepset{n,c}, engine.maximize); + %fprintf('%d sends %d\n', n, c); + msg{n,c} = normalize_pot(temp2); + end +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Entries new file mode 100644 index 00000000..a2b559af --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Entries @@ -0,0 +1,7 @@ +/belprop_mrf2_inf_engine.m/1.1.1.1/Fri Jan 3 22:01:56 2003// +/bp_mrf2.m/1.1.1.1/Mon Jan 5 01:23:34 2004// +/enter_soft_evidence.m/1.1.1.1/Thu Jan 2 17:29:54 2003// +/find_mpe.m/1.1.1.1/Thu Jan 2 17:49:18 2003// +/marginal_nodes.m/1.1.1.1/Tue Dec 31 21:24:30 2002// +/set_params.m/1.1.1.1/Thu Jan 2 17:28:56 2003// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Repository new file mode 100644 index 00000000..fe4612c3 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/belprop_mrf2_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/belprop_mrf2_inf_engine.m new file mode 100644 index 00000000..f7e9d695 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/belprop_mrf2_inf_engine.m @@ -0,0 +1,46 @@ +function engine = belprop_mrf2_inf_engine(mrf2, varargin) +% BELPROP_MRF2_INF_ENGINE Belief propagation for MRFs with discrete pairwise potentials +% engine = belprop_mrf2_inf_engine(mrf2, ...) +% +% This is like belprop_inf_engine, except it is designed for mrf2, so is much faster. +% +% [ ... ] = belprop_mrf2_inf_engine(..., 'param1',val1, 'param2',val2, ...) +% allows you to specify optional parameters as name/value pairs. +% Parameters modifying behavior of enter_evidence are below [default value in brackets] +% +% max_iter - max. num. iterations [ 5*nnodes] +% momentum - weight assigned to old message in convex combination +% (useful for damping oscillations) [0] +% tol - tolerance used to assess convergence [1e-3] +% verbose - 1 means print error at every iteration [0] +% +% Parameters can be changed later using set_params + + +% The advantages of pairwise potentials are +% (1) we can compute messages using vector-matrix multiplication +% (2) we can easily specify the parameters: one potential per edge +% In contrast, potentials on larger cliques are more complicated to deal with. + + +nnodes = length(mrf2.adj_mat); + +[engine.max_iter, engine.momentum, engine.tol, engine.verbose] = ... + process_options(varargin, 'max_iter', [], 'momentum', 0, 'tol', 1e-3, ... + 'verbose', 0); + +if isempty(engine.max_iter) % no user supplied value, so compute default + engine.max_iter = 5*nnodes; + %if acyclic(mrf2.adj_mat, 0) --- can be very slow! + % engine.max_iter = nnodes; + %else + % engine.max_iter = 5*nnodes; + %end +end + +engine.bel = cell(1, nnodes); % store results of enter_evidence here +engine.mrf2 = mrf2; + +engine = class(engine, 'belprop_mrf2_inf_engine'); + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/bp_mrf2.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/bp_mrf2.m new file mode 100644 index 00000000..90baaba1 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/bp_mrf2.m @@ -0,0 +1,209 @@ +function [new_bel, niter, new_msg, edge_id, nstates] = bp_mrf2_general(adj_mat, pot, local_evidence, varargin) +% BP_MRF2_GENERAL Belief propagation on an MRF with pairwise potentials +% function [bel, niter] = bp_mrf2_general(adj_mat, pot, local_evidence, varargin) +% +% Input: +% adj_mat(i,j) = 1 iff there is an edge between nodes i and j +% pot(ki,kj,i,j) or pot{i,j}(ki,kj) = potential on edge between nodes i,j +% If the potentials on all edges are the same, +% you can just pass in 1 array, pot(ki,kj) +% local_evidence(state, node) or local_evidence{i}(k) = Pr(observation at node i | Xi=k) +% +% Use cell arrays if the hidden nodes do not all have the same number of values. +% +% Output: +% bel(k,i) or bel{i}(k) = P(Xi=k|evidence) +% niter contains the number of iterations used +% +% [ ... ] = bp_mrf2(..., 'param1',val1, 'param2',val2, ...) +% allows you to specify optional parameters as name/value pairs. +% Parameters names are below [default value in brackets] +% +% max_iter - max. num. iterations [ 5*nnodes] +% momentum - weight assigned to old message in convex combination +% (useful for damping oscillations) - currently ignored i[0] +% tol - tolerance used to assess convergence [1e-3] +% maximize - 1 means use max-product, 0 means use sum-product [0] +% verbose - 1 means print error at every iteration [0] +% +% fn - name of function to call at end of every iteration [ [] ] +% fnargs - we call feval(fn, bel, iter, fnargs{:}) [ [] ] + +nnodes = length(adj_mat); + +[max_iter, momentum, tol, maximize, verbose, fn, fnargs] = ... + process_options(varargin, 'max_iter', 5*nnodes, 'momentum', 0, ... + 'tol', 1e-3, 'maximize', 0, 'verbose', 0, ... + 'fn', [], 'fnargs', []); + +if iscell(local_evidence) + use_cell = 1; +else + use_cell = 0; + [nstates nnodes] = size(local_evidence); +end + +if iscell(pot) + tied_pot = 0; +else + tied_pot = (ndims(pot)==2); +end + + +% give each edge a unique number +ndx = find(adj_mat); +nedges = length(ndx); +edge_id = zeros(1, nnodes*nnodes); +edge_id(ndx) = 1:nedges; +edge_id = reshape(edge_id, nnodes, nnodes); + +% initialise messages +if use_cell + prod_of_msgs = cell(1, nnodes); + old_bel = cell(1, nnodes); + nstates = zeros(1, nnodes); + old_msg = cell(1, nedges); + for i=1:nnodes + nstates(i) = length(local_evidence{i}); + prod_of_msgs{i} = local_evidence{i}; + old_bel{i} = local_evidence{i}; + end + for i=1:nnodes + nbrs = find(adj_mat(:,i)); + for j=nbrs(:)' + old_msg{edge_id(i,j)} = normalise(ones(nstates(j),1)); + end + end +else + prod_of_msgs = local_evidence; + old_bel = local_evidence; + %old_msg = zeros(nstates, nnodes, nnodes); + old_msg = zeros(nstates, nedges); + m = normalise(ones(nstates,1)); + for i=1:nnodes + nbrs = find(adj_mat(:,i)); + for j=nbrs(:)' + old_msg(:, edge_id(i,j)) = m; + %old_msg(:,i,j) = m; + end + end +end + + +converged = 0; +iter = 1; + +while ~converged & (iter <= max_iter) + + % each node sends a msg to each of its neighbors + for i=1:nnodes + nbrs = find(adj_mat(i,:)); + for j=nbrs(:)' + if tied_pot + pot_ij = pot; + else + if iscell(pot) + pot_ij = pot{i,j}; + else + pot_ij = pot(:,:,i,j); + end + end + pot_ij = pot_ij'; % now pot_ij(xj, xi) + % so pot_ij * msg(xi) = sum_xi pot(xj,xi) msg(xi) = f(xj) + + if 1 + % Compute temp = product of all incoming msgs except from j + % by dividing out old msg from j from the product of all msgs sent to i + if use_cell + temp = prod_of_msgs{i}; + m = old_msg{edge_id(j,i)}; + else + temp = prod_of_msgs(:,i); + m = old_msg(:, edge_id(j,i)); + end + if any(m==0) + fprintf('iter=%d, send from i=%d to j=%d\n', iter, i, j); + keyboard + end + m = m + (m==0); % valid since m(k)=0 => temp(k)=0, so can replace 0's with anything + temp = temp ./ m; + temp_div = temp; + end + + if 1 + % Compute temp = product of all incoming msgs except from j in obvious way + if use_cell + %temp = ones(nstates(i),1); + temp = local_evidence{i}; + for k=nbrs(:)' + if k==j, continue, end; + temp = temp .* old_msg{edge_id(k,i)}; + end + else + %temp = ones(nstates,1); + temp = local_evidence(:,i); + for k=nbrs(:)' + if k==j, continue, end; + temp = temp .* old_msg(:, edge_id(k,i)); + end + end + end + %assert(approxeq(temp, temp_div)) + assert(approxeq(normalise(pot_ij * temp), normalise(pot_ij * temp_div))) + + if maximize + newm = max_mult(pot_ij, temp); % bottleneck + else + newm = pot_ij * temp; + end + newm = normalise(newm); + if use_cell + new_msg{edge_id(i,j)} = newm; + else + new_msg(:, edge_id(i,j)) = newm; + end + end % for j + end % for i + old_prod_of_msgs = prod_of_msgs; + + % each node multiplies all its incoming msgs and computes its local belief + if use_cell + for i=1:nnodes + nbrs = find(adj_mat(:,i)); + prod_of_msgs{i} = local_evidence{i}; + for j=nbrs(:)' + prod_of_msgs{i} = prod_of_msgs{i} .* new_msg{edge_id(j,i)}; + end + new_bel{i} = normalise(prod_of_msgs{i}); + end + err = abs(cat(1,new_bel{:}) - cat(1, old_bel{:})); + else + for i=1:nnodes + nbrs = find(adj_mat(:,i)); + prod_of_msgs(:,i) = local_evidence(:,i); + for j=nbrs(:)' + prod_of_msgs(:,i) = prod_of_msgs(:,i) .* new_msg(:,edge_id(j,i)); + end + new_bel(:,i) = normalise(prod_of_msgs(:,i)); + end + err = abs(new_bel(:) - old_bel(:)); + end + converged = all(err < tol); + if verbose, fprintf('error at iter %d = %f\n', iter, sum(err)); end + if ~isempty(fn) + if isempty(fnargs) + feval(fn, new_bel); + else + feval(fn, new_bel, iter, fnargs{:}); + end + end + + iter = iter + 1; + old_msg = new_msg; + old_bel = new_bel; +end % while + +niter = iter-1; + +fprintf('converged in %d iterations\n', niter); + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/enter_soft_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/enter_soft_evidence.m new file mode 100644 index 00000000..032ca064 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/enter_soft_evidence.m @@ -0,0 +1,15 @@ +function [engine, ll, niter] = enter_soft_evidence(engine, local_evidence) +% ENTER_SOFT_EVIDENCE Propagate evidence using belief propagation +% [engine, ll, niter] = enter_soft_evidence(engine, local_evidence) +% +% local_evidence{i}(j) = Pr(observation at node i | S(i)=j) +% +% The log-likelihood is not computed; ll = 0. +% niter contains the number of iterations used + +ll = 0; +mrf2 = engine.mrf2; +[bel, niter] = bp_mrf2(mrf2.adj_mat, mrf2.pot, local_evidence, ... + 'max_iter', engine.max_iter, 'momentum', engine.momentum, ... + 'tol', engine.tol, 'maximize', 0, 'verbose', engine.verbose); +engine.bel = bel; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/find_mpe.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/find_mpe.m new file mode 100644 index 00000000..fbd91265 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/find_mpe.m @@ -0,0 +1,12 @@ +function mpe = find_mpe(engine, local_evidence) +% FIND_MPE Find the most probable explanation of the data +% function mpe = find_mpe(engine, local_evidence +% +% local_evidence{i}(j) = Pr(observation at node i | S(i)=j) +% +% This finds the marginally most likely value for each hidden node. +% It may give inconsistent results if there are ties. + +[mpe, niter] = bp_mpe_mrf2(engine.mrf2.adj_mat, engine.mrf2.pot, local_evidence, ... + 'max_iter', engine.max_iter, 'momentum', engine.momentum, ... + 'tol', engine.tol); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..c51ed666 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/marginal_nodes.m @@ -0,0 +1,10 @@ +function marginal = marginal_nodes(engine, query) +% MARGINAL_NODES Compute the marginal on the specified query nodes (belprop) +% marginal = marginal_nodes(engine, query) +% +% query must be a single node + +if length(query)>1 + error('can only handle single node marginals') +end +marginal = engine.bel{query}; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/set_params.m b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/set_params.m new file mode 100644 index 00000000..f5328006 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@belprop_mrf2_inf_engine/set_params.m @@ -0,0 +1,15 @@ +function engine = set_params(engine, varargin) +% SET_PARAMS Modify parameters of the inference engine +% engine = set_params(engine, 'param1',val1, 'param2',val2, ...) +% +% Parameter names are listed below. +% +% max_iter - max. num. iterations +% momentum - weight assigned to old message in convex combination +% (useful for damping oscillations) +% tol - tolerance used to assess convergence +% verbose - 1 means print error at every iteration [0] + +[engine.max_iter, engine.momentum, engine.tol, engine.verbose] = ... + process_options('max_iter', engine.max_iter, 'momentum', engine.momentum, ... + 'tol', engine.tol, 'verbose', engine.verbose); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/CVS/Entries new file mode 100644 index 00000000..a79c7562 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/CVS/Entries @@ -0,0 +1,4 @@ +/cond_gauss_inf_engine.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// +/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/CVS/Repository new file mode 100644 index 00000000..41961f94 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@cond_gauss_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/cond_gauss_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/cond_gauss_inf_engine.m new file mode 100644 index 00000000..166ed4cd --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/cond_gauss_inf_engine.m @@ -0,0 +1,23 @@ +function engine = cond_gauss_inf_engine(bnet) +% COND_GAUSS_INF_ENGINE Conditional Gaussian inference engine +% engine = cond_gauss_inf_engine(bnet) +% +% Enumerates all the discrete roots, and runs jtree on the remaining Gaussian nodes. + +dnodes = mysetdiff(1:length(bnet.dag), bnet.cnodes); + +%onodes = dnodes; % all the discrete ndoes will be observed +%engine.sub_engine = jtree_inf_engine(bnet, onodes); +bnet2 = bnet; +bnet2.observed = dnodes; +engine.sub_engine = jtree_inf_engine(bnet2); + +% This is where we will store the results between enter_evidence and marginal_nodes +engine.T = []; +engine.mu = []; +engine.Sigma = []; +engine.joint_dmarginal = []; +engine.onodes = []; % needed for marginal_nodes +engine.evidence = []; % needed for marginal_nodes add_ev + +engine = class(engine, 'cond_gauss_inf_engine', inf_engine(bnet)); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/enter_evidence.m new file mode 100644 index 00000000..db5019b1 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/enter_evidence.m @@ -0,0 +1,57 @@ +function [engine, loglik] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Add the specified evidence to the network (cond_gauss) +% [engine, loglik] = enter_evidence(engine, evidence, ...) +% +% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector) + +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes(:); +observed = ~isemptycell(evidence); +onodes = find(observed); +hnodes = find(isemptycell(evidence)); +engine.evidence = evidence; + +% check there are no C->D links where C is hidden +pot_type = determine_pot_type(bnet, onodes); + +dhid = myintersect(hnodes, bnet.dnodes); +S = prod(ns(dhid)); +T = zeros(S,1); + +N = length(bnet.dag); +mu = cell(1,N); +Sigma = cell(1,N); +cobs = myintersect(bnet.cnodes, onodes); +chid = myintersect(bnet.cnodes, hnodes); +ens = ns; +ens(cobs) = 0; +for j=chid(:)' + mu{j} = zeros(ens(j), S); + Sigma{j} = zeros(ens(j), ens(j), S); +end + +for i=1:S + dvals = ind2subv(ns(dhid), i); + evidence(dhid) = num2cell(dvals); + [sub_engine, loglik] = enter_evidence(engine.sub_engine, evidence); + for j=chid(:)' + m = marginal_nodes(sub_engine, j); + mu{j}(:,i) = m.mu; + Sigma{j}(:,:,i) = m.Sigma; + end + T(i) = exp(loglik); +end + +[T, lik] = normalise(T); +loglik = log(lik); + +engine.T = T; +engine.mu = mu; +engine.Sigma = Sigma; + +dnodes = bnet.dnodes; +dobs = myintersect(dnodes, onodes); +ens(dobs) = 1; +engine.joint_dmarginal = dpot(dnodes, ens(dnodes), myreshape(engine.T, ens(dnodes))); + +engine.onodes = onodes; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..9c5d60a7 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@cond_gauss_inf_engine/marginal_nodes.m @@ -0,0 +1,36 @@ +function marginal = marginal_nodes(engine, query, add_ev) +% MARGINAL_NODES Compute the marginal on the specified query nodes (cond_gauss) +% marginal = marginal_nodes(engine, query, add_ev) +% +% 'query' must be a singleton set +% 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 + +if length(query) ~= 1 + error('cond_gauss_inf_engine can only handle marginal queries on single nodes') +end +j = query; +bnet = bnet_from_engine(engine); + +if myismember(j, bnet.cnodes) + if ~myismember(j, engine.onodes) + [m, C] = collapse_mog(engine.mu{j}, engine.Sigma{j}, engine.T); + marginal.mu = m; + marginal.Sigma = C; + marginal.T = 1.0; % single mixture component + else + marginal.mu = engine.evidence{j}; + k = bnet.node_sizes(j); + marginal.Sigma = zeros(k,k); + marginal.T = 1.0; % since P(E|E)=1 + end +else + marginal = pot_to_marginal(marginalize_pot(engine.joint_dmarginal, j)); + if add_ev + marginal = add_ev_to_dmarginal(marginal, engine.evidence, bnet.node_sizes); + end +end + +marginal.domain = query; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/CVS/Entries new file mode 100644 index 00000000..e4399482 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/CVS/Entries @@ -0,0 +1,4 @@ +/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/enumerative_inf_engine.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/static/@enumerative_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/CVS/Repository new file mode 100644 index 00000000..ee8672a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@enumerative_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/enter_evidence.m new file mode 100644 index 00000000..eeb2193c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/enter_evidence.m @@ -0,0 +1,10 @@ +function [engine, loglik] = enter_evidence(engine, evidence) +% ENTER_EVIDENCE Add the specified evidence to the network (enumerative_inf) +% [engine, loglik] = enter_evidence(engine, evidence) +% +% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector) + +engine.evidence = evidence; +if nargout == 2 + [m, loglik] = marginal_nodes(engine, []); +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/enumerative_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/enumerative_inf_engine.m new file mode 100644 index 00000000..c31c64c9 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/enumerative_inf_engine.m @@ -0,0 +1,11 @@ +function engine = enumerative_inf_engine(bnet) +% ENUMERATIVE_INF_ENGINE Inference engine for fully discrete BNs that uses exhaustive enumeration. +% engine = enumerative_inf_engine(bnet) + + +assert(isempty(bnet.cnodes)); + +% This is where we store stuff between enter_evidence and marginal_nodes +engine.evidence = []; + +engine = class(engine, 'enumerative_inf_engine', inf_engine(bnet)); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..1c31eae1 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@enumerative_inf_engine/marginal_nodes.m @@ -0,0 +1,41 @@ +function [marginal, loglik] = marginal_nodes(engine, query) +% MARGINAL_NODES Compute the marginal on the specified query nodes (enumerative_inf) +% [marginal, loglik] = marginal_nodes(engine, query) + + +if isempty(query) & nargout < 2 + marginal.T = 1; + marginal.domain = []; + return; +end + +evidence = engine.evidence; +bnet = bnet_from_engine(engine); +assert(isempty(bnet.cnodes)); +n = length(bnet.dag); +observed = ~isemptycell(evidence); +vals = cat(1,evidence{observed}); +vals = vals(:)'; +ns = bnet.node_sizes; + +sz = ns(query); +T = 0*myones(sz); +p = 0; +for i=1:prod(ns) + inst = ind2subv(ns, i); % i'th instantiation + if isempty(vals) | inst(observed) == vals % agrees with evidence + prob = exp(log_lik_complete(bnet, num2cell(inst(:)))); + p = p + prob; + v = inst(query); + j = subv2ind(sz, v); + T(j) = T(j) + prob; + end +end + +[T, lik] = normalise(T); +lik = p; +loglik = log(lik); + +Tsmall = shrink_obs_dims_in_table(T, query, evidence); +marginal.domain = query; +marginal.T = Tsmall; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/CVS/Entries new file mode 100644 index 00000000..16ace516 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/CVS/Entries @@ -0,0 +1,4 @@ +/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/gaussian_inf_engine.m/1.1.1.1/Fri May 14 01:13:26 2004// +/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002// +D/private//// diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/CVS/Repository new file mode 100644 index 00000000..26418ea5 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@gaussian_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/enter_evidence.m new file mode 100644 index 00000000..c509a725 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/enter_evidence.m @@ -0,0 +1,46 @@ +function [engine, loglik] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Add the specified evidence to the network (gaussian_inf_engine) +% [engine, loglik] = enter_evidence(engine, evidence, ...) +% +% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector) + +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes; +O = find(~isemptycell(evidence)); +H = find(isemptycell(evidence)); +vals = cat(1, evidence{O}); + +% Compute Pr(H|o) +[Hmu, HSigma, loglik] = condition_gaussian(engine.mu, engine.Sigma, H, O, vals(:), ns); + +engine.Hmu = Hmu; +engine.HSigma = HSigma; +engine.hnodes = H; + +%%%%%%%% + +function [mu2, Sigma2, loglik] = condition_gaussian(mu, Sigma, X, Y, y, ns) +% CONDITION_GAUSSIAN Compute Pr(X|Y=y) where X and Y are jointly Gaussian. +% [mu2, Sigma2, ll] = condition_gaussian(mu, Sigma, X, Y, y, ns) + +if isempty(y) + mu2 = mu; + Sigma2 = Sigma; + loglik = 0; + return; +end + +use_log = 1; + +if length(Y)==length(mu) % instantiating every variable + mu2 = y; + Sigma2 = zeros(length(y)); + loglik = gaussian_prob(y, mu, Sigma, use_log); + return; +end + +[muX, muY, SXX, SXY, SYX, SYY] = partition_matrix_vec(mu, Sigma, X, Y, ns); +K = SXY*inv(SYY); +mu2 = muX + K*(y-muY); +Sigma2 = SXX - K*SYX; +loglik = gaussian_prob(y, muY, SYY, use_log); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/gaussian_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/gaussian_inf_engine.m new file mode 100644 index 00000000..3e34c166 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/gaussian_inf_engine.m @@ -0,0 +1,25 @@ +function engine = gaussian_inf_engine(bnet) +% GAUSSIAN_INF_ENGINE Computes the joint multivariate Gaussian corresponding to the bnet +% engine = gaussian_inf_engine(bnet) +% +% For details on how to compute the joint Gaussian from the bnet, see +% - "Gaussian Influence Diagrams", R. Shachter and C. R. Kenley, Management Science, 35(5):527--550, 1989. +% Once we have the Gaussian, we can apply the standard formulas for conditioning and marginalization. + +assert(isequal(bnet.cnodes, 1:length(bnet.dag))); + +[W, D, mu] = extract_params_from_gbn(bnet); +U = inv(eye(size(W)) - W')'; +Sigma = U' * D * U; + +engine.mu = mu; +engine.Sigma = Sigma; +%engine.logp = log(normal_coef(Sigma)); + +% This is where we will store the results between enter_evidence and marginal_nodes +engine.Hmu = []; +engine.HSigma = []; +engine.hnodes = []; + +engine = class(engine, 'gaussian_inf_engine', inf_engine(bnet)); + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..f3142cd5 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/marginal_nodes.m @@ -0,0 +1,15 @@ +function marginal = marginal_nodes(engine, query) +% MARGINAL_NODES Compute the marginal on the specified query nodes (gaussian) +% marginal = marginal_nodes(engine, query) + +% Compute sum_{Hsum} Pr(Hkeep, Hsum | o) +H = engine.hnodes; +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes; +Hkeep = myintersect(H, query); +Hsum = mysetdiff(H, Hkeep); + +[marginal.mu, marginal.Sigma] = marginalize_gaussian(engine.Hmu, engine.HSigma, Hkeep, Hsum, ns); +marginal.domain = query; +marginal.T = 1; + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/CVS/Entries new file mode 100644 index 00000000..de387328 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/CVS/Entries @@ -0,0 +1,2 @@ +/extract_params_from_gbn.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/CVS/Repository new file mode 100644 index 00000000..15f3d8c4 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@gaussian_inf_engine/private diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/extract_params_from_gbn.m b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/extract_params_from_gbn.m new file mode 100644 index 00000000..86345830 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gaussian_inf_engine/private/extract_params_from_gbn.m @@ -0,0 +1,38 @@ +function [B,D,mu] = extract_params_from_gbn(bnet) +% Extract all the local parameters of each Gaussian node, and collect them into global matrices. +% [B,D,mu] = extract_params_from_gbn(bnet) +% +% B(i,j) is a block matrix that contains the transposed weight matrix from node i to node j. +% D(i,i) is a block matrix that contains the noise covariance matrix for node i. +% mu(i) is a block vector that contains the shifted noise mean for node i. + +% In Shachter's model, the mean of each node in the global gaussian is +% the same as the node's local unconditional mean. +% In Alag's model (which we use), the global mean gets shifted. + + +num_nodes = length(bnet.dag); +bs = bnet.node_sizes(:); % bs = block sizes +N = sum(bs); % num scalar nodes + +B = zeros(N,N); +D = zeros(N,N); +mu = zeros(N,1); + +for i=1:num_nodes % in topological order + ps = parents(bnet.dag, i); + e = bnet.equiv_class(i); + %[m, Sigma, weights] = extract_params_from_CPD(bnet.CPD{e}); + s = struct(bnet.CPD{e}); % violate privacy of object + m = s.mean; Sigma = s.cov; weights = s.weights; + if length(ps) == 0 + mu(block(i,bs)) = m; + else + mu(block(i,bs)) = m + weights * mu(block(ps,bs)); + end + B(block(ps,bs), block(i,bs)) = weights'; + D(block(i,bs), block(i,bs)) = Sigma; +end + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Entries new file mode 100644 index 00000000..c19ebdd4 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Entries @@ -0,0 +1,4 @@ +/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/gibbs_sampling_inf_engine.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/private//// diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Repository new file mode 100644 index 00000000..3338daf9 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/enter_evidence.m new file mode 100644 index 00000000..0710d5c8 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/enter_evidence.m @@ -0,0 +1,29 @@ +function [engine, loglik] = enter_evidence(engine, evidence) +% ENTER_EVIDENCE Add the specified evidence to the network (gibbs_sampling_inf_engine) +% [engine, loglik] = enter_evidence(engine, evidence) +% +% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value +% +% loglik is not computed... we just return a 0 value + +bnet = bnet_from_engine(engine); + +engine.hnodes = find(isemptycell(evidence)); +engine.onodes = mysetdiff(1:length(evidence), engine.hnodes); + +engine.evidence = zeros(engine.slice_size, 1); + +% Reset all counts since they are no longer valid +engine.marginal_counts = {}; +%engine.state = sample_bnet (bnet, 1, 0); +engine.state = cell2num(sample_bnet(bnet)); + +% For speed, we use a normal (not cell) array. We're making use of +% the current restriction to discrete nodes. +for i = engine.onodes + engine.evidence(i) = evidence{i}; +end + +loglik = 0; + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/gibbs_sampling_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/gibbs_sampling_inf_engine.m new file mode 100644 index 00000000..3dc4b361 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/gibbs_sampling_inf_engine.m @@ -0,0 +1,104 @@ +function engine = gibbs_sampling_inf_engine(bnet, varargin) +% GIBBS_SAMPLING_INF_ENGINE +% +% engine = gibbs_sampling_inf_engine(bnet, ...) +% +% Optional parameters [default in brackets] +% 'burnin' - How long before you start using the samples [100]. +% 'gap' - how often you use the samples in the estimate [1]. +% 'T' - number of samples [1000] +% i.e, number of node flips (so, for +% example if there are 10 nodes in the bnet, and T is 1000, each +% node will get flipped 100 times (assuming a deterministic schedule)) +% The total running time is proportional to burnin + T*gap. +% +% 'order' - if the sampling schedule is deterministic, use this +% parameter to specify the order in which nodes are sampled. +% Order is allowed to include multiple copies of nodes, which is +% useful if you want to, say, focus sampling on particular nodes. +% Default is to use a deterministic schedule that goes through the +% nodes in order. +% +% 'sampling_dist' - when using a stochastic sampling method, at +% each step the node to sample is chosen according to this +% distribution (may be unnormalized) +% +% The sampling_dist and order parameters shouldn't both be used, +% and this will cause an assert. +% +% +% Written by "Bhaskara Marthi" <bhaskara@cs.berkeley.edu> Feb 02. + + +engine.burnin = 100; +engine.gap = 1; +engine.T = 1000; +use_default_order = 1; +engine.deterministic = 1; +engine.order = {}; +engine.sampling_dist = {}; + +if nargin >= 2 + args = varargin; + nargs = length(args); + for i = 1:2:nargs + switch args{i} + case 'burnin' + engine.burnin = args{i+1}; + case 'gap' + engine.gap = args{i+1}; + case 'T' + engine.T = args{i+1}; + case 'order' + assert (use_default_order); + use_default_order = 0; + engine.order = args{i+1}; + case 'sampling_dist' + assert (use_default_order); + use_default_order = 0; + engine.deterministic = 0; + engine.sampling_dist = args{i+1}; + otherwise + error(['unrecognized parameter to gibbs_sampling_inf_engine']); + end + end +end + +engine.slice_size = size(bnet.dag, 2); +if (use_default_order) + engine.order = 1:engine.slice_size; +end +engine.hnodes = []; +engine.onodes = []; +engine.evidence = []; +engine.state = []; +engine.marginal_counts = {}; + +% Precompute the strides for each CPT +engine.strides = compute_strides(bnet); + +% Precompute graphical information +engine.families = compute_families(bnet); +engine.children = compute_children(bnet); + +% For convenience, store the CPTs as tables rather than objects +engine.CPT = get_cpts(bnet); + +engine = class(engine, 'gibbs_sampling_inf_engine', inf_engine(bnet)); + + + + + + + + + + + + + + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..8df75552 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/marginal_nodes.m @@ -0,0 +1,135 @@ +function [marginal, engine] = marginal_nodes(engine, nodes, varargin); +% MARGINAL_NODES Compute the marginal on the specified query nodes +% (gibbs_sampling_engine) +% [marginal, engine] = marginal_nodes(engine, nodes, ...) +% +% returns Pr(X(nodes) | X(observedNodes)) +% +% The engine is also modified, and so it is returned as well, since +% Matlab doesn't support passing by reference(!) So +% if you want to, for example, incrementally run gibbs for a few 100 +% steps at a time, you should use the returned value. +% +% Optional arguments : +% +% 'reset_counts' is 1 if you want to reset the counts made in the +% past, and 0 otherwise (if the current query nodes are different +% from the previous query nodes, or if marginal_nodes has not been +% called before, reset_counts should be set to 1). +% By default it is 1. + + +reset_counts = 1; + +if (nargin > 3) + args = varargin; + nargs = length(args); + for i = 1:2:nargs + switch args{i} + case 'reset_counts' + reset_counts = args{i+1}; + otherwise + error(['Incorrect argument to gibbs_sampling_engine/' ... + ' marginal_nodes']); + end + end +end + +% initialization stuff +bnet = bnet_from_engine(engine); +slice_size = engine.slice_size; +hnodes = engine.hnodes; +onodes = engine.onodes; +nonqnodes = mysetdiff(1:slice_size, nodes); +gap = engine.gap; +burnin = engine.burnin; +T_max = engine.T; +ns = bnet.node_sizes(nodes); + + +% Cache the strides for the marginal table +marg_strides = [1 cumprod(ns(1:end-1))]; + +% Reset counts if necessary +if (reset_counts == 1) + %state = sample_bnet(bnet, 1, 0); + %state = cell2num(sample_bnet(bnet, 'evidence', num2cell(engine.evidence))); + state = cell2num(sample_bnet(bnet)); + state(onodes) = engine.evidence(onodes); + if (length(ns) == 1) + marginal_counts = zeros(ns(1),1); + else + marginal_counts = zeros(ns); + end + +% Otherwise, use the counts that have been stored in the engine +else + state = engine.state; + state(onodes, :) = engine.evidence(onodes, :); + marginal_counts = engine.marginal_counts; +end + +if (engine.deterministic == 1) + pos = 1; + order = engine.order; + orderSize = length(engine.order); +else + sampling_dist = normalise(engine.sampling_dist); +end + + +for t = 1:(T_max*gap+burnin) + + % First, select node m to sample + if (engine.deterministic == 1) + m = engine.order(pos); + pos = pos+1; + if (pos > orderSize) + pos = 1; + end + else + m = my_sample_discrete(sampling_dist); + end + + + % If the node is observed, then don't bother resampling + if (myismember(m, onodes)) + continue; + end + + % Next, compute the posterior + post = compute_posterior (bnet, state, m, engine.strides, engine.families, ... + engine.children, engine.CPT); + state(m) = my_sample_discrete(post); + + % Now update our monte carlo estimate of the posterior + % distribution on the query node + if ((mod(t-burnin, gap) == 0) & (t > burnin)) + + vals = state(nodes); + index = 1+marg_strides*(vals-1); + marginal_counts(index) = marginal_counts(index)+1; + end +end + +% Store results for future computation. Note that we store +% unnormalized counts +engine.state = state; +engine.marginal_counts = marginal_counts; + +marginal.T = normalise(marginal_counts); + + + + + + + + + + + + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CPT.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CPT.m new file mode 100644 index 00000000..772f137c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CPT.m @@ -0,0 +1,5 @@ +function c = CPT(bnet, i) +% CPT Helper function avoid having to type in +% CPD_to_CPT(bnet.CPD{i}) every time + +c = CPD_to_CPT(bnet.CPD{i}); \ No newline at end of file diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Entries new file mode 100644 index 00000000..0919a694 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Entries @@ -0,0 +1,13 @@ +/CPT.m/1.1.1.1/Wed May 29 15:59:56 2002// +/compute_children.m/1.1.1.1/Wed May 29 15:59:56 2002// +/compute_families.m/1.1.1.1/Wed May 29 15:59:56 2002// +/compute_families_dbn.m/1.1.1.1/Wed May 29 15:59:56 2002// +/compute_posterior.c/1.1.1.1/Wed May 29 15:59:56 2002// +/compute_posterior_dbn.m/1.1.1.1/Wed May 29 15:59:56 2002// +/compute_strides.m/1.1.1.1/Wed May 29 15:59:56 2002// +/get_cpts.m/1.1.1.1/Wed May 29 15:59:56 2002// +/get_slice_dbn.c/1.1.1.1/Wed May 29 15:59:56 2002// +/get_slice_dbn.m/1.1.1.1/Wed May 29 15:59:56 2002// +/my_sample_discrete.m/1.1.1.1/Wed May 29 15:59:56 2002// +/sample_single_discrete.c/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Repository new file mode 100644 index 00000000..a3027631 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_children.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_children.m new file mode 100644 index 00000000..3af799f8 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_children.m @@ -0,0 +1,12 @@ +function c = compute_children(bnet) +% COMPUTE_CHILDREN +% precomputes the children of nodes in a bnet +% +% The return value is a cell array for now + +ss = size(bnet.dag, 1); +c = cell(ss, 1); +for i = 1:ss + c{i} = children(bnet.dag, i); +end + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_families.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_families.m new file mode 100644 index 00000000..e75974cc --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_families.m @@ -0,0 +1,12 @@ +function families = compute_families(bnet) +% COMPUTE_FAMILIES +% precomputes the families of nodes in a bnet +% +% The return value is a cell array for now + +ss = size(bnet.dag, 1); +families = cell(ss, 1); +for i = 1:ss + families{i} = family(bnet.dag, i); +end + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_families_dbn.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_families_dbn.m new file mode 100644 index 00000000..7647bc28 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_families_dbn.m @@ -0,0 +1,13 @@ +function families = compute_families_dbn(bnet) +% COMPUTE_FAMILIES +% precomputes the families of nodes in a dbn +% +% The return value is a cell array for now + +ss = size(bnet.intra, 1); +families = cell(ss, 2); +for i = 1:ss + families{i, 1} = family(bnet.dag, i, 1); + families{i, 2} = family(bnet.dag, i, 2); +end + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior.c b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior.c new file mode 100644 index 00000000..3c61b7f3 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior.c @@ -0,0 +1,107 @@ +#include "mex.h" + +/* Helper function that extracts a one-dimensional slice from a cpt */ +/* +void multiplySlice(mxArray *bnet, mxArray *state, int i, int nsi, int j, + mxArray *strides, mxArray *fam, mxArray *cpts, + double *y) +*/ +void multiplySlice(const mxArray *bnet, const mxArray *state, int i, int nsi, int j, + const mxArray *strides, const mxArray *fam, const mxArray *cpts, + double *y) +{ + mxArray *ec, *cpt, *family; + double *ecElts, *cptElts, *famElts, *strideElts, *ev; + int c1, k, famSize, startInd, strideStride, pos, stride; + + strideStride = mxGetM(strides); + strideElts = mxGetPr(strides); + + ev = mxGetPr(state); + + /* Get the CPT */ + ec = mxGetField (bnet, 0, "equiv_class"); + ecElts = mxGetPr(ec); + k = (int) ecElts[j-1]; + cpt = mxGetCell (cpts, k-1); + cptElts = mxGetPr (cpt); + + /* Get the family vector for this cpt */ + family = mxGetCell (fam, j-1); + famSize = mxGetNumberOfElements (family); + famElts = mxGetPr (family); + + /* Figure out starting position and stride */ + startInd = 0; + for (c1 = 0, pos = k-1; c1 < famSize; c1++, pos +=strideStride) { + if (famElts[c1] != i) { + startInd += strideElts[pos]*(ev[(int)famElts[c1]-1]-1); + } + else { + stride = strideElts[pos]; + } + } + + for (c1 = 0, pos = startInd; c1 < nsi; c1++, pos+=stride) { + y[c1] *= cptElts[pos]; + } +} + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray + *prhs[]) +{ + double *pi, *nsElts, *y, *childrenElts; + mxArray *ns, *children; + double sum; + int i, nsi, c1, numChildren; + + pi = mxGetPr(prhs[2]); + i = (int) pi[0]; + + ns = mxGetField(prhs[0], 0, "node_sizes"); + nsElts = mxGetPr(ns); + nsi = (int) nsElts[i-1]; + + /* Initialize the posterior */ + plhs[0] = mxCreateDoubleMatrix (1, nsi, mxREAL); + y = mxGetPr(plhs[0]); + for (c1 = 0; c1 < nsi; c1++) { + y[c1] = 1; + } + + /* Multiply in the cpt of the node i */ + multiplySlice(prhs[0], prhs[1], i, nsi, i, prhs[3], prhs[4], + prhs[6], y); + + + /* Multiply in cpts of children of i */ + children = mxGetCell (prhs[5], i-1); + numChildren = mxGetNumberOfElements (children); + childrenElts = mxGetPr (children); + + for (c1 = 0; c1 < numChildren; c1++) { + int j; + j = (int) childrenElts[c1]; + multiplySlice (prhs[0], prhs[1], i, nsi, j, prhs[3], prhs[4], + prhs[6], y); + } + + sum = 0; + /* normalize! */ + for (c1 = 0; c1 < nsi; c1++) { + sum += y[c1]; + } + + for (c1 = 0; c1 < nsi; c1++) { + y[c1] /= sum; + } +} + + + + + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior_dbn.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior_dbn.m new file mode 100644 index 00000000..e9a69b24 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior_dbn.m @@ -0,0 +1,59 @@ +function post = compute_posterior_dbn(bnet, state, i, n, strides, families, ... + CPT) +% COMPUTE_POSTERIOR +% +% post = compute_posterior(bnet, state, i, n, strides, families, +% cpts) +% +% Compute the posterior distribution on node X_i^n of a DBN, +% conditional on evidence in the cell array state +% +% strides is the cached result of compute_strides(bnet) +% families is the cached result of compute_families(bnet) +% cpt is the cached result of get_cpts(bnet) +% +% post is a one-dimensional table + + + +% First multiply in the cpt of the node itself +post = get_slice_dbn(bnet, state, i, n, i, n, strides, families, CPT); +post = post(:); + +% Then multiply in CPTs of children that are in this slice +for j = children(bnet.intra, i) + slice = get_slice_dbn(bnet, state, j, n, i, n, strides, families, CPT); + post = post.*slice(:); +end + +% Finally, if necessary, multiply in CPTs of children in the next +% slice +if (n < size(state,2)) + for j = children(bnet.inter, i) + slice = get_slice_dbn(bnet, state, j, n+1, i, n, strides, families, ... + CPT); + post = post.*slice(:); + end +end + +post = normalise(post); + + + + + + + + + + + + + + + + + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_strides.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_strides.m new file mode 100644 index 00000000..a8e26c25 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_strides.m @@ -0,0 +1,27 @@ +function strides = compute_strides(bnet) +% COMPUTE_STRIDES For each CPT and each variable in that CPT, +% returns the stride of that variable. So in future, we can +% quickly extract a slice of the CPT. +% +% The return value is a 2d array, where strides(i,j) contains the +% stride of the jth variable in the ith CPT. Cell arrays would +% have saved space but they are slower. +% + +num_cpts = size(bnet.CPD, 2); +max_cpt_dim = 1 + max(sum(bnet.dag)); +strides = zeros(num_cpts, max_cpt_dim); + +for i = 1:num_cpts + c = CPT(bnet, i); + siz = size(CPT(bnet, i)); + + % Deal with the special case of a 1-d array separately + if siz(2) == 1 + dim = 1; + else + dim = size(siz, 2); + end + + strides(i, 1:dim ) = [1 cumprod(siz(1:dim-1))]; +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_cpts.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_cpts.m new file mode 100644 index 00000000..77c86070 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_cpts.m @@ -0,0 +1,8 @@ +function c = get_cpts(bnet) +% Get all the cpts in tabular form + +cpds = bnet.CPD; +c = cell(size(cpds)); +for i = 1:length(c) + c{i} = CPT(bnet, i); +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.c b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.c new file mode 100644 index 00000000..33540eff --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.c @@ -0,0 +1,116 @@ +#include "mex.h" + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray + *prhs[]) +{ + double *pn, *pi, *pj, *pm, *y, *ecElts, *pcpt, *famElts, *strideElts, + *ev, *nsElts; + int i, k, j, m, n; + mxArray *ec, *cpt, *fam, *ns; + int c1, famSize, nsj; + int strideStride, startInd, stride, pos, numNodes; + + const int BNET = 0; + const int STATE = 1; + const int STRIDES = 6; + const int FAMILIES = 7; + const int CPT = 8; + + pn = mxGetPr(prhs[3]); + n = (int) pn[0]; + pi = mxGetPr(prhs[2]); + i = (int) pi[0]; + pj = mxGetPr(prhs[4]); + j = (int) pj[0]; + pm = mxGetPr(prhs[5]); + m = (int) pm[0]; + ev = mxGetPr(prhs[STATE]); + ns = mxGetField (prhs[BNET], 0, "node_sizes"); + nsElts = mxGetPr (ns); + numNodes = mxGetM(ns); + + strideStride = mxGetM(prhs[STRIDES]); + strideElts = mxGetPr(prhs[STRIDES]); + + + + /* Treat the case n = 1 separately */ + if (pn[0] == 1) { + + /* Get the appropriate CPT */ + ec = mxGetField (prhs[BNET], 0, "eclass1"); + ecElts = mxGetPr(ec); + k = (int) ecElts[i-1]; + cpt = mxGetCell (prhs[8], k-1); + pcpt = mxGetPr(cpt); + + nsj = (int) nsElts[j-1]; + + /* Get the correct family vector */ + /* (Note : MEX is painful) */ + fam = mxGetCell (prhs[FAMILIES], i - 1); + famSize = mxGetNumberOfElements(fam); + famElts = mxGetPr(fam); + + + /* Figure out starting position and stride */ + startInd = 0; + for (c1 = 0, pos = k-1; c1 < famSize; c1++, pos+=strideStride) { + if (famElts[c1] != j) { + startInd += strideElts[pos]*(ev[(int)famElts[c1]-1]-1); + } + else { + stride = strideElts[pos]; + } + } + + plhs[0] = mxCreateDoubleMatrix (1, nsj, mxREAL); + y = mxGetPr(plhs[0]); + for (c1 = 0, pos = startInd; c1 < nsj; c1++, pos+=stride) { + y[c1] = pcpt[pos]; + } + } + + /* Handle the case n > 1 */ + else { + + /* Get the appropriate CPT */ + ec = mxGetField (prhs[BNET], 0, "eclass2"); + ecElts = mxGetPr(ec); + k = (int) ecElts[i-1]; + cpt = mxGetCell (prhs[8], k-1); + pcpt = mxGetPr(cpt); + + /* Figure out size of slice */ + if (m == 1) { + nsj = (int) nsElts[j-1]; + } + else { + nsj = (int) nsElts[j-1+numNodes]; + } + + /* Figure out family */ + fam = mxGetCell (prhs[FAMILIES], i - 1 + numNodes); + famSize = mxGetNumberOfElements(fam); + famElts = mxGetPr(fam); + + startInd = 0; + for (c1 = 0, pos = k-1; c1 < famSize; c1++, pos+=strideStride) { + int f = (int) famElts[c1]; + + if (((f == j+numNodes) && (m == n)) || ((f == j) && (m == + n-1))) { + stride = strideElts[pos]; + } + else { + startInd += strideElts[pos] * (ev[f-1+((n-2)*numNodes)]-1); + } + } + + plhs[0] = mxCreateDoubleMatrix(1,nsj, mxREAL); + y = mxGetPr(plhs[0]); + for (c1 = 0, pos = startInd; c1 < nsj; c1++, pos+=stride) { + y[c1] = pcpt[pos]; + } + } +} diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.m new file mode 100644 index 00000000..22841784 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.m @@ -0,0 +1,87 @@ +function slice = get_slice_dbn(bnet, state, i, n, j, m, strides, families, ... + CPT) +% slice = get_slice(bnet, state, i, n, j, m, strides, families, cpt) +% +% GET_SLICE get one-dimensional slice of the CPT for node X_i^n +% that corresponds to the different values of X_j^m, where all +% other nodes have values given by state. +% strides is the result of +% calling compute_strides(bnet) +% families is the result of calling compute_families(bnet) +% cpts is the result of calling get_cpts(bnet) +% +% slice is a 1-d array + + +if (n == 1) + + k = bnet.eclass1(i); + c = CPT{k}; + + % Figure out evidence on family + fam = families{i, 1}; + ev = state(fam, 1); + + % Remove evidence on node j + pos = find(fam == j); + ev(pos) = 1; + dim = size(ev, 1); + + % Compute initial index and stride + start_ind = 1+strides(k, 1:dim)*(ev-1); + stride = strides(k, pos); + + % Compute the slice + slice = c(start_ind:stride:start_ind+(bnet.node_sizes(j, 1)-1)*stride); + +else + + k = bnet.eclass2(i); + c = CPT{k}; + + fam = families{i, 2}; + ss = length(bnet.intra); + + % Divide the family into nodes in this time step and nodes in the + % previous time step + this_time_step = fam(find(fam > ss)); + prev_time_step = fam(find(fam <= ss)); + + % Normalize the node numbers + this_time_step = this_time_step - ss; + + % Get the evidence + this_step_ev = state(this_time_step, n); + prev_step_ev = state(prev_time_step, n-1); + + % Remove the evidence for X_j^m + if (m == n) + pos = find(this_time_step == j); + this_step_ev(pos) = 1; + pos = pos + size(prev_time_step, 2); + else + assert (m == n-1); + pos = find(prev_time_step == j); + prev_step_ev(pos) = 1; + end + + % Combine the two time steps + ev = [prev_step_ev; this_step_ev]; + dim = size(ev, 1); + + + % Compute starting index and stride + start_ind = 1 + strides(k, 1:dim)*(ev-1); + stride = strides(k, pos); + + % Compute slice + if (m == 1) + q = 1; + else + q = 2; + end + slice = c(start_ind:stride:start_ind+(bnet.node_sizes(j, q)-1)*stride); +end + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/my_sample_discrete.m b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/my_sample_discrete.m new file mode 100644 index 00000000..70f0615b --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/my_sample_discrete.m @@ -0,0 +1,7 @@ +function M = my_sample_discrete(prob) +% A faster version that calls a c subfunction. Will update one +% day to have r and c parameters as well + +R = rand (1,1); +M = sample_single_discrete(R, prob); + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/sample_single_discrete.c b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/sample_single_discrete.c new file mode 100644 index 00000000..36112de6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@gibbs_sampling_inf_engine/private/sample_single_discrete.c @@ -0,0 +1,22 @@ +#include "mex.h" + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray + *prhs[]) +{ + double *y, *pr, *dist; + int k, distSize; + double r, cumSum; + + plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL); + y = mxGetPr (plhs[0]); + + pr = mxGetPr (prhs[0]); + r = pr[0]; + + dist = mxGetPr (prhs[1]); + distSize = mxGetNumberOfElements (prhs[1]); + + for (k = 0, cumSum = 0; (k < distSize) && (r >= cumSum); cumSum += dist[k], k++); + + y[0] = k; +} diff --git a/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/CVS/Entries new file mode 100644 index 00000000..1c5d76dd --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/CVS/Entries @@ -0,0 +1,6 @@ +/enter_evidence.m/1.1.1.1/Mon Jun 7 19:05:42 2004// +/find_mpe.m/1.1.1.1/Wed Jun 19 21:56:32 2002// +/global_joint_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002// +/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002// +/marginal_nodes.m/1.1.1.1/Mon Jun 7 19:04:48 2004// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/CVS/Repository new file mode 100644 index 00000000..0c8fadf5 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@global_joint_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/enter_evidence.m new file mode 100644 index 00000000..105894ff --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/enter_evidence.m @@ -0,0 +1,42 @@ +function [engine, loglik] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Add the specified evidence to the network (global_joint) +% [engine, loglik] = enter_evidence(engine, evidence, ...) +% +% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value. +% +% Warning: Computing the log likelihood requires marginalizing all the nodes and can be slow. +% +% The list below gives optional arguments [default value in brackets]. +% +% exclude - list of nodes whose potential will not be included in the joint [ [] ] +% +% e.g., engine = enter_evidence(engine, ev, 'exclude', 3) + +exclude = []; +maximize = 0; + +if nargin >= 3 + args = varargin; + nargs = length(args); + for i=1:2:nargs + switch args{i}, + case 'exclude', exclude = args{i+1}; + case 'maximize', maximize = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + +assert(~maximize) +bnet = bnet_from_engine(engine); +N = length(bnet.node_sizes); +%[engine.jpot, loglik] = compute_joint_pot(bnet, mysetdiff(1:N, exclude), evidence, 1:N); +[engine.jpot] = compute_joint_pot(bnet, mysetdiff(1:N, exclude), evidence, 1:N); +% jpot should not be normalized, otherwise it gives wrong resutls for limids like asia_dt1 +if nargout == 2 + [m] = marginal_nodes(engine, []); + [T, lik] = normalize(m.T); + loglik = log(lik); +end +%[engine.jpot loglik] = normalize_pot(engine.jpot); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/find_mpe.m b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/find_mpe.m new file mode 100644 index 00000000..92915b6c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/find_mpe.m @@ -0,0 +1,28 @@ +function [mpe, ll] = find_mpe(engine, evidence) +% FIND_MPE_GLOBAL Compute the most probable explanation(s) from the global joint +% [mpe, ll] = find_mpe(engine, evidence) +% +% mpe(k,i) is the most probable value of node i in the k'th global mode (cell array) +% +% We assume all nodes are discrete + +%engine = global_joint_inf_engine(bnet); +bnet = bnet_from_engine(engine); +engine = enter_evidence(engine, evidence); +S1 = struct(engine); % violate object privacy +S2 = struct(S1.jpot); % joint potential +prob = max(S2.T(:)); +modes = find(S2.T(:) == prob); + +ens = bnet.node_sizes; +onodes = find(~isemptycell(evidence)); +ens(onodes) = 1; +mpe = ind2subv(ens, modes); +for k=1:length(modes) + for i=onodes(:)' + mpe(k,i) = evidence{i}; + end +end +ll = log(prob); + +mpe = num2cell(mpe); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/global_joint_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/global_joint_inf_engine.m new file mode 100644 index 00000000..86bca532 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/global_joint_inf_engine.m @@ -0,0 +1,8 @@ +function engine = global_joint_inf_engine(bnet) +% GLOBAL_JOINT_INF_ENGINE Construct the global joint distribution as a potential +% engine = global_joint_inf_engine(bnet) +% +% Warning: this has size exponential in the number of discrete hidden variables + +engine.jpot = []; +engine = class(engine, 'global_joint_inf_engine', inf_engine(bnet)); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/marginal_family.m b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/marginal_family.m new file mode 100644 index 00000000..6931814c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/marginal_family.m @@ -0,0 +1,7 @@ +function [m, pot] = marginal_family(engine, i) +% MARGINAL_FAMILY Compute the marginal on i's family (global_inf_engine) +% [m, pot] = marginal_family(engine, i) +% + +bnet = bnet_from_engine(engine); +[m, pot] = marginal_nodes(engine, family(bnet.dag, i)); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..223e6574 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@global_joint_inf_engine/marginal_nodes.m @@ -0,0 +1,8 @@ +function [m, pot] = marginal_nodes(engine, query) +% MARGINAL_NODES Compute the marginal on the specified set of nodes (global_joint) +% [m, pot] = marginal_nodes(engine, query) + +pot = marginalize_pot(engine.jpot, query); +m = pot_to_marginal(pot); +%[m.T, lik] = normalize(m.T); +%loglik = log(lik); 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 diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/CVS/Entries new file mode 100644 index 00000000..932cb3b4 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/CVS/Entries @@ -0,0 +1,5 @@ +/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/jtree_limid_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002// +/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// +D/Old//// diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/CVS/Repository new file mode 100644 index 00000000..e8bf097c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@jtree_limid_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_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_limid_inf_engine/Old/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Entries new file mode 100644 index 00000000..0b350b99 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Entries @@ -0,0 +1,3 @@ +/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002// +/marginal_nodes_SS.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Repository new file mode 100644 index 00000000..59988183 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_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_limid_inf_engine/Old/marginal_family.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/marginal_family.m new file mode 100644 index 00000000..cd660ae4 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/marginal_family.m @@ -0,0 +1,59 @@ +function [m, pot] = marginal_family(engine, query) +% MARGINAL_NODES Compute the marginal on the family of the specified node (jtree_limid) +% [m, pot] = marginal_family(engine, query) +% +% query should be a single decision node, or [] (to compute global max expected utility) + +bnet = bnet_from_engine(engine); +if isempty(query) + compute_meu = 1; + d = bnet.decision_nodes(1); % pick an arbitrary root to collect to + fam = []; % marginalize root pot down to a point +else + compute_meu = 0; + d = query; + assert(myismember(d, bnet.decision_nodes)); + fam = family(bnet.dag, d); +end + +clpot = init_clpot(bnet, engine.cliques, engine.clq_ass_to_node, engine.evidence, engine.exclude); + +% collect to root (clique containing d) +C = length(engine.cliques); +seppot = cell(C, C); % separators are implicitely initialized to 1s +for n=engine.postorder{d}(1:end-1) + for p=parents(engine.rooted_jtree{d}, 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}); + clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n}); + end +end + +root = engine.clq_ass_to_node(d); +assert(root == engine.postorder{d}(end)); +pot = marginalize_pot(clpot{root}, fam); +m = pot_to_marginal(pot); + +%%%%%%%%%%% + + +function clpot = init_clpot(bnet, cliques, clq_ass_to_node, evidence, exclude) + +% Set the clique potentials to all 1s +C = length(cliques); +clpot = cell(1, C); +ns = bnet.node_sizes; +for i=1:C + clpot{i} = upot(cliques{i}, ns(cliques{i})); +end + +N = length(bnet.dag); +nodes = mysetdiff(1:N, exclude); + +for n=nodes(:)' + fam = family(bnet.dag, n); + e = bnet.equiv_class(n); + c = clq_ass_to_node(n); + pot = convert_to_pot(bnet.CPD{e}, 'u', ns, fam, evidence); + clpot{c} = multiply_by_pot(clpot{c}, pot); +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/marginal_nodes_SS.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/marginal_nodes_SS.m new file mode 100644 index 00000000..2b6ff642 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/Old/marginal_nodes_SS.m @@ -0,0 +1,52 @@ +function [pot, MEU] = marginal_nodes(engine, d) + +C = length(cliques); +%clpot = init_clpot(limid, cliques, d, clq_ass_to_node); +clpot = init_clpot(limid, cliques, [], clq_ass_to_node); + +% collect to root +if 1 + % HUGIN + seppot = cell(C, C); % separators are implicitely initialized to 1s + for n=postorder{di}(1:end-1) + for p=parents(rooted_jtree{di}, 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}); + clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n}); + end + end +else + % Shafer-Shenoy + msg = cell(C,C); + for n=postorder{di}(1:end-1) + for c=children(rooted_jtree{di}, n) + clpot{n} = multiply_by_pot(clpot{n}, msg{c,n}); + end + p = parents(rooted_jtree{di}, n); + %msg{n,p} = marginalize_pot(clpot{n}, cliques{p}); + msg{n,p} = marginalize_pot(clpot{n}, separator{n,p}); + end + root = clq_ass_to_node(d); + n=postorder{di}(end); + assert(n == root); + for c=children(rooted_jtree{di}, n) + clpot{n} = multiply_by_pot(clpot{n}, msg{c,n}); + end +end + +fam = family(limid.dag, d); +pot = marginalize_pot(clpot{root}, fam); + +%%%%%%% +jpot = compute_joint_pot_limid(limid); +pot2 = marginalize_pot(jpot, fam); +assert(approxeq_pot(pot, pot2)) +%%%%%% + +[policy, score] = extract_policy(pot); + +e = limid.equiv_class(d); +limid.CPD{e} = set_params(limid.CPD{e}, 'policy', policy); + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/enter_evidence.m new file mode 100644 index 00000000..5d874803 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/enter_evidence.m @@ -0,0 +1,28 @@ +function engine = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Add the specified evidence to the network (jtree_limid) +% engine = enter_evidence(engine, evidence, ...) +% +% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value. +% +% The list below gives optional arguments [default value in brackets]. +% +% exclude - list of nodes whose potential will not be included in the joint [ [] ] +% +% e.g., engine = enter_evidence(engine, ev, 'exclude', 3) + +exclude = []; + +if nargin >= 3 + args = varargin; + nargs = length(args); + for i=1:2:nargs + switch args{i}, + case 'exclude', exclude = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + +engine.exclude = exclude; +engine.evidence = evidence; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/jtree_limid_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/jtree_limid_inf_engine.m new file mode 100644 index 00000000..83dd89ef --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/jtree_limid_inf_engine.m @@ -0,0 +1,52 @@ +function engine = jtree_limid_inf_engine(bnet) +% JTREE_LIMID_INF_ENGINE Make a junction tree engine for use by solve_limid +% engine = jtree_limid_inf_engine(bnet) +% +% This engine is designed to compute marginals on decision nodes + + +MG = moralize(bnet.dag); +% We do not remove the utility nodes, because that complicates the book-keeping. +% Leaving them in will not introduce any un-necessary triangulation arcs, because they are always leaves. +% Also, since utility nodes have size 1, they do not increase the size of the potentials. + +ns = bnet.node_sizes; +elim_order = best_first_elim_order(MG, ns); +[MTG, engine.cliques] = triangulate(MG, elim_order); +[engine.jtree, root, B, w] = cliques_to_jtree(engine.cliques, ns); + +% 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. +N = length(bnet.dag); +engine.clq_ass_to_node = zeros(1, N); +for i=1:N + 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 + + +% Compute the separators between connected cliques. +[is,js] = find(engine.jtree > 0); +num_cliques = length(engine.cliques); +engine.separator = cell(num_cliques, num_cliques); +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 + + +% create |D| different rooted jtree's +engine.rooted_jtree = cell(1, N); +engine.preorder = cell(1, N); +engine.postorder = cell(1, N); +for d=bnet.decision_nodes(:)' + root = engine.clq_ass_to_node(d); + [engine.rooted_jtree{d}, engine.preorder{d}, engine.postorder{d}] = mk_rooted_tree(engine.jtree, root); +end + +engine.exclude = []; +engine.evidence = []; + +engine = class(engine, 'jtree_limid_inf_engine', inf_engine(bnet)); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/marginal_family.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/marginal_family.m new file mode 100644 index 00000000..dd3bf95e --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/marginal_family.m @@ -0,0 +1,52 @@ +function [m, pot] = marginal_family(engine, query) +% MARGINAL_NODES Compute the marginal on the family of the specified node (jtree_limid) +% [m, pot] = marginal_family(engine, query) +% +% query should be a single decision node + +bnet = bnet_from_engine(engine); +d = query; +assert(myismember(d, bnet.decision_nodes)); +fam = family(bnet.dag, d); + +clpot = init_clpot(bnet, engine.cliques, engine.clq_ass_to_node, engine.evidence, engine.exclude); + +% collect to root (clique containing d) +C = length(engine.cliques); +seppot = cell(C, C); % separators are implicitely initialized to 1s +for n=engine.postorder{d}(1:end-1) + for p=parents(engine.rooted_jtree{d}, 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}); + clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n}); + end +end + +root = engine.clq_ass_to_node(d); +assert(root == engine.postorder{d}(end)); +pot = marginalize_pot(clpot{root}, fam); +m = pot_to_marginal(pot); + +%%%%%%%%%%% + + +function clpot = init_clpot(bnet, cliques, clq_ass_to_node, evidence, exclude) + +% Set the clique potentials to all 1s +C = length(cliques); +clpot = cell(1, C); +ns = bnet.node_sizes; +for i=1:C + clpot{i} = upot(cliques{i}, ns(cliques{i})); +end + +N = length(bnet.dag); +nodes = mysetdiff(1:N, exclude); + +for n=nodes(:)' + fam = family(bnet.dag, n); + e = bnet.equiv_class(n); + c = clq_ass_to_node(n); + pot = convert_to_pot(bnet.CPD{e}, 'u', fam(:), evidence); + clpot{c} = multiply_by_pot(clpot{c}, pot); +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..d3700270 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_limid_inf_engine/marginal_nodes.m @@ -0,0 +1,17 @@ +function [m, pot] = marginal_nodes(engine, query) +% MARGINAL_NODES Compute the marginal on the specified nodes (jtree_limid) +% [m, pot] = marginal_nodes(engine, query) +% +% query should be a subset of a family of a decision node + +if isempty(query) + bnet = bnet_from_engine(engine); + d = bnet.decision_nodes(1); % pick an arbitrary decision node + [dummy, big_pot] = marginal_family(engine, d); +else + [dummy, big_pot] = marginal_family(engine, query); +end +pot = marginalize_pot(big_pot, query); +m = pot_to_marginal(pot); + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Entries new file mode 100644 index 00000000..33ee0f34 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Entries @@ -0,0 +1,4 @@ +/enter_evidence.m/1.1.1.1/Mon Jun 17 20:30:02 2002// +/find_mpe.m/1.1.1.1/Mon Jun 17 20:29:40 2002// +/jtree_mnet_inf_engine.m/1.1.1.1/Sat Jan 18 22:13:32 2003// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Repository new file mode 100644 index 00000000..2deff959 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@jtree_mnet_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_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_mnet_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/enter_evidence.m new file mode 100644 index 00000000..97546f4b --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/enter_evidence.m @@ -0,0 +1,82 @@ +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}; + 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 + +% 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); + +% 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_mnet_inf_engine/find_mpe.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/find_mpe.m new file mode 100644 index 00000000..f5c04ba8 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_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); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/jtree_mnet_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/jtree_mnet_inf_engine.m new file mode 100644 index 00000000..ff21ae47 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_mnet_inf_engine/jtree_mnet_inf_engine.m @@ -0,0 +1,101 @@ +function engine = jtree_mnet_inf_engine(model, varargin) +% JTREE_MNET_INF_ENGINE Junction tree inference engine for Markov nets +% engine = jtree_inf_engine(mnet, ...) +% + +% set default params +N = length(mnet.graph); +root = N; + +engine = init_fields; +engine = class(engine, 'jtree_mnet_inf_engine', inf_engine(bnet)); + +onodes = bnet.observed; +if is_mnet(bnet) + MG = bnet.graph; +else + error('should be a mnet') +end + +%[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(MG, 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); +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_sparse_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Entries new file mode 100644 index 00000000..cc6f3f5b --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Entries @@ -0,0 +1,12 @@ +/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.c/1.1.1.1/Wed May 29 15:59:56 2002// +/distribute_evidence.c/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// +/init_pot.c/1.1.1.1/Wed May 29 15:59:56 2002// +/jtree_sparse_inf_engine.m/1.1.1.1/Sat Jan 18 22:11:32 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_sparse_inf_engine/CVS/Entries.Log b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Entries.Log new file mode 100644 index 00000000..61d96f3f --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Entries.Log @@ -0,0 +1 @@ +A D/old//// diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Repository new file mode 100644 index 00000000..ccd02123 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@jtree_sparse_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_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_sparse_inf_engine/cliques_from_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/cliques_from_engine.m new file mode 100644 index 00000000..cd9d871d --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_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_sparse_inf_engine/clq_containing_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/clq_containing_nodes.m new file mode 100644 index 00000000..8904fa49 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_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_sparse_inf_engine/collect_evidence.c b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/collect_evidence.c new file mode 100644 index 00000000..8480c701 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/collect_evidence.c @@ -0,0 +1,634 @@ +/* C mex for collect_evidence.c in @jtree_sparse_inf_engine directory */ +/* File enter_evidence.m in directory @jtree_sparse_inf_engine call it*/ + +/******************************************/ +/* collect_evidence has 3 input & 2 output*/ +/* engine */ +/* clpot */ +/* seppot */ +/* */ +/* clpot */ +/* seppot */ +/******************************************/ + +#include <math.h> +#include <stdlib.h> +#include "mex.h" + +int compare(const void* src1, const void* src2){ + int i1 = *(int*)src1 ; + int i2 = *(int*)src2 ; + return i1-i2 ; +} + +void ind_subv(int index, const int *cumprod, int n, int *bsubv){ + int i; + + for (i = n-1; i >= 0; i--) { + bsubv[i] = ((int)floor(index / cumprod[i])); + index = index % cumprod[i]; + } +} + +int subv_ind(const int n, const int *cumprod, const int *subv){ + int i, index=0; + + for(i=0; i<n; i++){ + index += subv[i] * cumprod[i]; + } + return index; +} + +void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){ + int i, j; + int *eff_cumprod, *subv, *diffsize, *diff_cumprod; + + subv = malloc(diffdim * sizeof(int)); + eff_cumprod = malloc(diffdim * sizeof(int)); + diffsize = malloc(diffdim * sizeof(int)); + diff_cumprod = malloc(diffdim * sizeof(int)); + for(i=0; i<diffdim; i++){ + eff_cumprod[i] = bCumprod[dmask[i]]; + diffsize[i] = (int)pbSize[dmask[i]]; + } + diff_cumprod[0] = 1; + for(i=0; i<diffdim-1; i++){ + diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i]; + } + for(i=0; i<ND; i++){ + ind_subv(i, diff_cumprod, diffdim, subv); + weight[i] = 0; + for(j=0; j<diffdim; j++){ + weight[i] += eff_cumprod[j] * subv[j]; + } + } + free(eff_cumprod); + free(subv); + free(diffsize); + free(diff_cumprod); +} + +void reset_nzmax(mxArray *spArray, const int old_nzmax, const int new_nzmax){ + double *ptr; + void *newptr; + int *ir, *jc; + int nbytes; + + if(new_nzmax == old_nzmax) return; + nbytes = new_nzmax * sizeof(*ptr); + ptr = mxGetPr(spArray); + newptr = mxRealloc(ptr, nbytes); + mxSetPr(spArray, newptr); + nbytes = new_nzmax * sizeof(*ir); + ir = mxGetIr(spArray); + newptr = mxRealloc(ir, nbytes); + mxSetIr(spArray, newptr); + jc = mxGetJc(spArray); + jc[0] = 0; + jc[1] = new_nzmax; + mxSetNzmax(spArray, new_nzmax); +} + +mxArray* convert_ill_table_to_sparse(const double *Table, const int *sequence, const int nzCounts, const int N){ + mxArray *spTable; + int i, temp, *irs, *jcs, count=0; + double *sr; + + spTable = mxCreateSparse(N, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + irs[i] = sequence[count]; + count++; + temp = sequence[count]; + sr[i] = Table[temp]; + count++; + } + return spTable; +} + +void multiply_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex, nzCounts=0; + int *samemask, *diffmask, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *sequence, *weight; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *spr, *bpr; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + if(sdim == 0){ + pTemp = mxCreateSparse(NB, 1, NB, mxREAL); + mxSetField(bigPot, 0, "T", pTemp); + bpr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + sjc[0] = 0; + sjc[1] = NB; + for(i=0; i<NB; i++){ + bpr[i] = *spr; + sir[i] = i; + } + return; + } + + NS = 1; + for(i=0; i<sdim; i++){ + NS *= (int)psSize[i]; + } + ND = NB / NS; + + if(ND == 1){ + pTemp1 = mxGetField(smallPot, 0, "T"); + pTemp = mxDuplicateArray(pTemp1); + mxSetField(bigPot, 0, "T", pTemp); + return; + } + + + NZB = ND * NZS; + + diffdim = bdim - sdim; + sequence = malloc(NZB * 2 * sizeof(int)); + bigTable = malloc(NZB * sizeof(double)); + samemask = malloc(sdim * sizeof(int)); + diffmask = malloc(diffdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + weight = malloc(ND * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + count1 = 0; + for(i=0; i<bdim; i++){ + match = 0; + for(j=0; j<sdim; j++){ + if(pbDomain[i] == psDomain[j]){ + samemask[count] = i; + match = 1; + count++; + break; + } + } + if(match == 0){ + diffmask[count1] = i; + count1++; + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim); + for(i=0; i<NZS; i++){ + sindex = sir[i]; + ind_subv(sindex, sCumprod, sdim, ssubv); + temp = 0; + for(j=0; j<sdim; j++){ + temp += ssubv[j] * bCumprod[samemask[j]]; + } + for(j=0; j<ND; j++){ + bindex = weight[j] + temp; + bigTable[nzCounts] = spr[i]; + sequence[count] = bindex; + count++; + sequence[count] = nzCounts; + nzCounts++; + count++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + qsort(sequence, nzCounts, sizeof(int) * 2, compare); + pTemp = convert_ill_table_to_sparse(bigTable, sequence, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(sequence); + free(bigTable); + free(samemask); + free(diffmask); + free(bCumprod); + free(sCumprod); + free(weight); + free(ssubv); +} + +void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0; + int *mask, *result, *bir, *sir, *rir, *bjc, *sjc, *rjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, *rpr; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + if(sdim == 0){ + for(i=0; i<NZB; i++){ + bpr[i] *= *spr; + } + return; + } + + pTemp1 = mxCreateSparse(NB, 1, NZB, mxREAL); + rpr = mxGetPr(pTemp1); + rir = mxGetIr(pTemp1); + rjc = mxGetJc(pTemp1); + rjc[0] = 0; + rjc[1] = NZB; + + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare); + if(result){ + position = result - sir; + rpr[nzCounts] = bpr[i] * spr[position]; + rir[nzCounts] = bindex; + nzCounts++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + reset_nzmax(pTemp1, NZB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp1); + + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + +mxArray* marginal_null_to_spPot(const mxArray *bigPot, const mxArray *sDomain, const int maximize){ + int i, j, count, bdim, sdim, NB, NS, ND; + int *mask, *sir, *sjc; + double *pbDomain, *psDomain, *pbSize, *psSize, *spr; + mxArray *pTemp, *smallPot; + const char *field_names[] = {"domain", "T", "sizes"}; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + psDomain = mxGetPr(sDomain); + sdim = mxGetNumberOfElements(sDomain); + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + + smallPot = mxCreateStructMatrix(1, 1, 3, field_names); + pTemp = mxDuplicateArray(sDomain); + mxSetField(smallPot, 0, "domain", pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + if(sdim == 0){ + pTemp = mxCreateSparse(1, 1, 1, mxREAL); + mxSetField(smallPot, 0, "T", pTemp); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + *spr = 0; + *sir = 0; + sjc[0] = 0; + sjc[1] = 1; + if(maximize) *spr = 1; + else *spr = NB; + + pTemp = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(pTemp) = 1; + mxSetField(smallPot, 0, "sizes", pTemp); + return smallPot; + } + + mask = malloc(sdim * sizeof(int)); + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + pTemp = mxCreateDoubleMatrix(1, count, mxREAL); + psSize = mxGetPr(pTemp); + NS = 1; + for(i=0; i<count; i++){ + psSize[i] = pbSize[mask[i]]; + NS *= (int)psSize[i]; + } + mxSetField(smallPot, 0, "sizes", pTemp); + + ND = NB / NS; + + pTemp = mxCreateSparse(NS, 1, NS, mxREAL); + mxSetField(smallPot, 0, "T", pTemp); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + if(maximize){ + for(i=0; i<NS; i++){ + spr[i] = 1; + sir[i] = i; + } + } + else{ + for(i=0; i<NS; i++){ + spr[i] = ND; + sir[i] = i; + } + } + sjc[0] = 0; + sjc[1] = NS; + + free(mask); + return smallPot; +} + +mxArray* marginal_spPot_to_spPot(const mxArray *bigPot, const mxArray *sDomain, const int maximize){ + int i, j, count, bdim, sdim, NB, NS, NZB, position, bindex, sindex, nzCounts=0; + int *mask, *sequence, *result, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *sTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr; + mxArray *pTemp, *smallPot; + const char *field_names[] = {"domain", "T", "sizes"}; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + psDomain = mxGetPr(sDomain); + sdim = mxGetNumberOfElements(sDomain); + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + smallPot = mxCreateStructMatrix(1, 1, 3, field_names); + pTemp = mxDuplicateArray(sDomain); + mxSetField(smallPot, 0, "domain", pTemp); + + if(sdim == 0){ + pTemp = mxCreateSparse(1, 1, 1, mxREAL); + mxSetField(smallPot, 0, "T", pTemp); + spr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + *spr = 0; + *bir = 0; + bjc[0] = 0; + bjc[1] = 1; + if(maximize){ + for(i=0; i<NZB; i++){ + *spr = (*spr < bpr[i])? bpr[i] : *spr; + } + } + else{ + for(i=0; i<NZB; i++){ + *spr += bpr[i]; + } + } + + pTemp = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(pTemp) = 1; + mxSetField(smallPot, 0, "sizes", pTemp); + return smallPot; + } + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + mask = malloc(sdim * sizeof(int)); + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + pTemp = mxCreateDoubleMatrix(1, count, mxREAL); + psSize = mxGetPr(pTemp); + NS = 1; + for(i=0; i<count; i++){ + psSize[i] = pbSize[mask[i]]; + NS *= (int)psSize[i]; + } + mxSetField(smallPot, 0, "sizes", pTemp); + + + sTable = malloc(NZB * sizeof(double)); + sequence = malloc(NZB * 2 * sizeof(double)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + for(i=0; i<NZB; i++)sTable[i] = 0; + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sequence, nzCounts, sizeof(int)*2, compare); + if(result){ + position = (result - sequence) / 2; + if(maximize) + sTable[position] = (sTable[position] < bpr[i]) ? bpr[i] : sTable[position]; + else sTable[position] += bpr[i]; + } + else { + if(maximize) + sTable[nzCounts] = (sTable[nzCounts] < bpr[i]) ? bpr[i] : sTable[nzCounts]; + else sTable[nzCounts] += bpr[i]; + sequence[count] = sindex; + count++; + sequence[count] = nzCounts; + nzCounts++; + count++; + } + } + + qsort(sequence, nzCounts, sizeof(int) * 2, compare); + pTemp = convert_ill_table_to_sparse(sTable, sequence, nzCounts, NS); + mxSetField(smallPot, 0, "T", pTemp); + + free(sTable); + free(sequence); + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); + + return smallPot; +} + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ + int i, n, p, np, pn, loop, loops, nCliques, temp, maximize; + int *collect_order; + double *pr, *pr1; + mxArray *pTemp, *pTemp1, *pPostP, *pClpot, *pSeppot, *pSeparator; + + pTemp = mxGetField(prhs[0], 0, "cliques"); + nCliques = mxGetNumberOfElements(pTemp); + loops = nCliques - 1; + pTemp = mxGetField(prhs[0], 0, "maximize"); + maximize = (int)mxGetScalar(pTemp); + pSeparator = mxGetField(prhs[0], 0, "separator"); + + collect_order = malloc(2 * loops * sizeof(int)); + + pTemp = mxGetField(prhs[0], 0, "postorder"); + pr = mxGetPr(pTemp); + pPostP = mxGetField(prhs[0], 0, "postorder_parents"); + for(i=0; i<loops; i++){ + temp = (int)pr[i] - 1; + pTemp = mxGetCell(pPostP, temp); + pr1 = mxGetPr(pTemp); + collect_order[i] = (int)pr1[0] - 1; + collect_order[i+loops] = temp; + } + + plhs[0] = mxDuplicateArray(prhs[1]); + plhs[1] = mxDuplicateArray(prhs[2]); + + for(loop=0; loop<loops; loop++){ + p = collect_order[loop]; + n = collect_order[loop+loops]; + np = p * nCliques + n; + pn = n * nCliques + p; + pClpot = mxGetCell(plhs[0], n); + pTemp1 = mxGetField(pClpot, 0, "T"); + pTemp = mxGetCell(pSeparator, pn); + if(pTemp1) + pSeppot = marginal_spPot_to_spPot(pClpot, pTemp, maximize); + else pSeppot = marginal_null_to_spPot(pClpot, pTemp, maximize); + mxSetCell(plhs[1], pn, pSeppot); + + pClpot = mxGetCell(plhs[0], p); + pTemp1 = mxGetField(pClpot, 0, "T"); + if(pTemp1) + multiply_spPot_by_spPot(pClpot, pSeppot); + else multiply_null_by_spPot(pClpot, pSeppot); + } + free(collect_order); +} + + + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/distribute_evidence.c b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/distribute_evidence.c new file mode 100644 index 00000000..8147c403 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/distribute_evidence.c @@ -0,0 +1,618 @@ +/* C mex for distribute_evidence.c in @jtree_sparse_inf_engine directory*/ +/* File enter_evidence.m in directory @jtree_sparse_inf_engine call it */ + +/*********************************************/ +/* distribute_evidence has 3 input & 2 output*/ +/* engine */ +/* clpot */ +/* seppot */ +/* */ +/* clpot */ +/* seppot */ +/*********************************************/ + +#include <math.h> +#include <stdlib.h> +#include "mex.h" + +int compare(const void* src1, const void* src2){ + int i1 = *(int*)src1 ; + int i2 = *(int*)src2 ; + return i1-i2 ; +} + +void ind_subv(int index, const int *cumprod, int n, int *bsubv){ + int i; + + for (i = n-1; i >= 0; i--) { + bsubv[i] = ((int)floor(index / cumprod[i])); + index = index % cumprod[i]; + } +} + +int subv_ind(const int n, const int *cumprod, const int *subv){ + int i, index=0; + + for(i=0; i<n; i++){ + index += subv[i] * cumprod[i]; + } + return index; +} + +void reset_nzmax(mxArray *spArray, const int old_nzmax, const int new_nzmax){ + double *ptr; + void *newptr; + int *ir, *jc; + int nbytes; + + if(new_nzmax == old_nzmax) return; + nbytes = new_nzmax * sizeof(*ptr); + ptr = mxGetPr(spArray); + newptr = mxRealloc(ptr, nbytes); + mxSetPr(spArray, newptr); + nbytes = new_nzmax * sizeof(*ir); + ir = mxGetIr(spArray); + newptr = mxRealloc(ir, nbytes); + mxSetIr(spArray, newptr); + jc = mxGetJc(spArray); + jc[0] = 0; + jc[1] = new_nzmax; + mxSetNzmax(spArray, new_nzmax); +} + +void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){ + int i, j; + int *eff_cumprod, *subv, *diffsize, *diff_cumprod; + + subv = malloc(diffdim * sizeof(int)); + eff_cumprod = malloc(diffdim * sizeof(int)); + diffsize = malloc(diffdim * sizeof(int)); + diff_cumprod = malloc(diffdim * sizeof(int)); + for(i=0; i<diffdim; i++){ + eff_cumprod[i] = bCumprod[dmask[i]]; + diffsize[i] = (int)pbSize[dmask[i]]; + } + diff_cumprod[0] = 1; + for(i=0; i<diffdim-1; i++){ + diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i]; + } + for(i=0; i<ND; i++){ + ind_subv(i, diff_cumprod, diffdim, subv); + weight[i] = 0; + for(j=0; j<diffdim; j++){ + weight[i] += eff_cumprod[j] * subv[j]; + } + } + free(eff_cumprod); + free(subv); + free(diffsize); + free(diff_cumprod); +} + +mxArray* convert_ill_table_to_sparse(const double *Table, const int *sequence, const int nzCounts, const int N){ + mxArray *spTable; + int i, temp, *irs, *jcs, count=0; + double *sr; + + spTable = mxCreateSparse(N, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + irs[i] = sequence[count]; + count++; + temp = sequence[count]; + sr[i] = Table[temp]; + count++; + } + return spTable; +} + +void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0; + int *mask, *result, *bir, *sir, *rir, *bjc, *sjc, *rjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, *rpr; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + if(sdim == 0){ + for(i=0; i<NZB; i++){ + bpr[i] *= *spr; + } + return; + } + + pTemp1 = mxCreateSparse(NB, 1, NZB, mxREAL); + rpr = mxGetPr(pTemp1); + rir = mxGetIr(pTemp1); + rjc = mxGetJc(pTemp1); + rjc[0] = 0; + rjc[1] = NZB; + + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare); + if(result){ + position = result - sir; + rpr[nzCounts] = bpr[i] * spr[position]; + rir[nzCounts] = bindex; + nzCounts++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + reset_nzmax(pTemp1, NZB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp1); + + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + +void marginal_spPot_to_spPot(const mxArray *bigPot, mxArray *smallPot, const int maximize){ + int i, j, count, bdim, sdim, NB, NS, NZB, position, bindex, sindex, nzCounts=0; + int *mask, *sequence, *result, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *sTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr; + mxArray *pTemp; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + NS = 1; + for(i=0; i<sdim; i++){ + NS *= (int)psSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + if(sdim == 0){ + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + *spr = 0; + if(maximize){ + for(i=0; i<NZB; i++){ + *spr = (*spr < bpr[i])? bpr[i] : *spr; + } + } + else{ + for(i=0; i<NZB; i++){ + *spr += bpr[i]; + } + } + return; + } + + mask = malloc(sdim * sizeof(int)); + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + + sTable = malloc(NZB * sizeof(double)); + sequence = malloc(NZB * 2 * sizeof(double)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + for(i=0; i<NZB; i++){ + sTable[i] = 0; + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sequence, nzCounts, sizeof(int)*2, compare); + if(result){ + position = (result - sequence) / 2; + if(maximize) + sTable[position] = (sTable[position] < bpr[i]) ? bpr[i] : sTable[position]; + else sTable[position] += bpr[i]; + } + else { + if(maximize) + sTable[nzCounts] = (sTable[nzCounts] < bpr[i]) ? bpr[i] : sTable[nzCounts]; + else sTable[nzCounts] += bpr[i]; + sequence[count] = sindex; + count++; + sequence[count] = nzCounts; + nzCounts++; + count++; + } + } + + pTemp = mxGetField(smallPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + qsort(sequence, nzCounts, sizeof(int) * 2, compare); + pTemp = convert_ill_table_to_sparse(sTable, sequence, nzCounts, NS); + mxSetField(smallPot, 0, "T", pTemp); + + free(sTable); + free(sequence); + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + +void divide_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex; + int *samemask, *diffmask, *rir, *rjc, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *weight; + double *pbDomain, *psDomain, *pbSize, *psSize, *rpr, *spr, value; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + if(sdim == 0){ + pTemp1 = mxGetField(bigPot, 0, "T"); + if(pTemp1)mxDestroyArray(pTemp1); + pTemp = mxCreateSparse(NB, 1, NB, mxREAL); + mxSetField(bigPot, 0, "T", pTemp); + rpr = mxGetPr(pTemp); + rir = mxGetIr(pTemp); + rjc = mxGetJc(pTemp); + rjc[0] = 0; + rjc[1] = NB; + value = *spr; + if(value == 0) value = 1; + for(i=0; i<NB; i++){ + rpr[i] = 1 / value; + rir[i] = i; + } + return; + } + + NS = 1; + for(i=0; i<sdim; i++){ + NS *= (int)psSize[i]; + } + ND = NB / NS; + + pTemp = mxCreateSparse(NB, 1, NB, mxREAL); + rpr = mxGetPr(pTemp); + rir = mxGetIr(pTemp); + rjc = mxGetJc(pTemp); + rjc[0] = 0; + rjc[1] = NB; + for(i=0; i<NB; i++){ + rpr[i] = 1; + rir[i] = i; + } + + NZB = ND * NZS; + + diffdim = bdim - sdim; + samemask = malloc(sdim * sizeof(int)); + diffmask = malloc(diffdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + weight = malloc(ND * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + count1 = 0; + for(i=0; i<bdim; i++){ + match = 0; + for(j=0; j<sdim; j++){ + if(pbDomain[i] == psDomain[j]){ + samemask[count] = i; + match = 1; + count++; + break; + } + } + if(match == 0){ + diffmask[count1] = i; + count1++; + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim); + for(i=0; i<NZS; i++){ + sindex = sir[i]; + ind_subv(sindex, sCumprod, sdim, ssubv); + temp = 0; + for(j=0; j<sdim; j++){ + temp += ssubv[j] * bCumprod[samemask[j]]; + } + for(j=0; j<ND; j++){ + bindex = weight[j] + temp; + rpr[bindex] = 1 / (spr[i]); + } + } + + pTemp1 = mxGetField(bigPot, 0, "T"); + if(pTemp1)mxDestroyArray(pTemp1); + mxSetField(bigPot, 0, "T", pTemp); + + free(samemask); + free(diffmask); + free(bCumprod); + free(sCumprod); + free(weight); + free(ssubv); +} + +void divide_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex; + int *mask, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp1 = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp1); + bir = mxGetIr(pTemp1); + bjc = mxGetJc(pTemp1); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + if(sdim == 0){ + value = *spr; + if(value == 0)value = 1; + for(i=0; i<NZB; i++){ + bpr[i] /= value; + } + return; + } + + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare); + if(result){ + position = result - sir; + bpr[i] /= spr[position]; + } + } + + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ + int i, j, loop, loops, nCliques, temp, count, parent, child, maximize, *distribute_order; + double *pr, *pr1; + mxArray *pTemp, *pPreCh, *pClpot, *pSeppot; + + pTemp = mxGetField(prhs[0], 0, "cliques"); + nCliques = mxGetNumberOfElements(pTemp); + loops = nCliques - 1; + pTemp = mxGetField(prhs[0], 0, "maximize"); + maximize = (int)mxGetScalar(pTemp); + + distribute_order = malloc(2 * loops * sizeof(int)); + pTemp = mxGetField(prhs[0], 0, "preorder"); + pr = mxGetPr(pTemp); + pPreCh = mxGetField(prhs[0], 0, "preorder_children"); + count = 0; + for(i=0; i<nCliques; i++){ + temp = (int)pr[i] - 1; + pTemp = mxGetCell(pPreCh, temp); + pr1 = mxGetPr(pTemp); + loop = mxGetNumberOfElements(pTemp); + for(j=0; j<loop; j++){ + distribute_order[count] = temp; + distribute_order[count + loops] = (int)pr1[j] - 1; + count++; + } + } + + plhs[0] = mxDuplicateArray(prhs[1]); + plhs[1] = mxDuplicateArray(prhs[2]); + + for(loop=0; loop<loops; loop++){ + parent = distribute_order[loop]; + child = distribute_order[loop+loops]; + i = nCliques * child + parent; + pClpot = mxGetCell(plhs[0], child); + pTemp = mxGetField(pClpot, 0, "T"); + pSeppot = mxGetCell(plhs[1], i); + if(pTemp){ + if(mxIsEmpty(pTemp)) + divide_null_by_spPot(pClpot, pSeppot); + else + divide_spPot_by_spPot(pClpot, pSeppot); + } + else divide_null_by_spPot(pClpot, pSeppot); + + pClpot = mxGetCell(plhs[0], parent); + marginal_spPot_to_spPot(pClpot, pSeppot, maximize); + mxSetCell(plhs[1], i, pSeppot); + + pClpot = mxGetCell(plhs[0], child); + multiply_spPot_by_spPot(pClpot, pSeppot); + } + free(distribute_order); +} diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/enter_evidence.m new file mode 100644 index 00000000..86041be2 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/enter_evidence.m @@ -0,0 +1,100 @@ +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); + +engine.evidence = evidence; % store this for marginal_nodes with add_ev option + +% 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); + 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); +[clpot, seppot] = distribute_evidence(engine, clpot, seppot); +C = length(clpot); +ll = zeros(1, C); +for i=1:C + domain = clpot{i}.domain; + sizes = clpot{i}.sizes; + T = clpot{i}.T; + clpot{i} = dpot(domain, sizes, T); +end + +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_sparse_inf_engine/enter_soft_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/enter_soft_evidence.m new file mode 100644 index 00000000..59671415 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/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_sparse_inf_engine/init_pot.c b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/init_pot.c new file mode 100644 index 00000000..86e09eae --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/init_pot.c @@ -0,0 +1,624 @@ +/* C mex init_pot for in @jtree_sparse_inf_engine directory */ +/* The file enter_evidence.m in directory @jtree_sparse_inf_engine call it*/ + +/**************************************/ +/* init_pot.c has 5 input & 2 output */ +/* engine */ +/* clqs */ +/* pots */ +/* pot_type */ +/* onodes */ +/* */ +/* clpot */ +/* seppot */ +/**************************************/ +#include <math.h> +#include <stdlib.h> +#include "mex.h" + +int compare(const void* src1, const void* src2){ + int i1 = *(int*)src1 ; + int i2 = *(int*)src2 ; + return i1-i2 ; +} + +void ind_subv(int index, const int *cumprod, int n, int *bsubv){ + int i; + + for (i = n-1; i >= 0; i--) { + bsubv[i] = ((int)floor(index / cumprod[i])); + index = index % cumprod[i]; + } +} + +int subv_ind(const int n, const int *cumprod, const int *subv){ + int i, index=0; + + for(i=0; i<n; i++){ + index += subv[i] * cumprod[i]; + } + return index; +} + +void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){ + int i, j; + int *eff_cumprod, *subv, *diffsize, *diff_cumprod; + + subv = malloc(diffdim * sizeof(int)); + eff_cumprod = malloc(diffdim * sizeof(int)); + diffsize = malloc(diffdim * sizeof(int)); + diff_cumprod = malloc(diffdim * sizeof(int)); + for(i=0; i<diffdim; i++){ + eff_cumprod[i] = bCumprod[dmask[i]]; + diffsize[i] = (int)pbSize[dmask[i]]; + } + diff_cumprod[0] = 1; + for(i=0; i<diffdim-1; i++){ + diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i]; + } + for(i=0; i<ND; i++){ + ind_subv(i, diff_cumprod, diffdim, subv); + weight[i] = 0; + for(j=0; j<diffdim; j++){ + weight[i] += eff_cumprod[j] * subv[j]; + } + } + free(eff_cumprod); + free(subv); + free(diffsize); + free(diff_cumprod); +} + +void reset_nzmax(mxArray *spArray, const int old_nzmax, const int new_nzmax){ + double *ptr; + void *newptr; + int *ir, *jc; + int nbytes; + + if(new_nzmax == old_nzmax) return; + nbytes = new_nzmax * sizeof(*ptr); + ptr = mxGetPr(spArray); + newptr = mxRealloc(ptr, nbytes); + mxSetPr(spArray, newptr); + nbytes = new_nzmax * sizeof(*ir); + ir = mxGetIr(spArray); + newptr = mxRealloc(ir, nbytes); + mxSetIr(spArray, newptr); + jc = mxGetJc(spArray); + jc[0] = 0; + jc[1] = new_nzmax; + mxSetNzmax(spArray, new_nzmax); +} + +mxArray* convert_ill_table_to_sparse(const double *bigTable, const int *sequence, const int nzCounts, const int NB){ + mxArray *spTable; + int i, temp, *irs, *jcs, count=0; + double *sr; + + spTable = mxCreateSparse(NB, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + irs[i] = sequence[count]; + count++; + temp = sequence[count]; + sr[i] = bigTable[temp]; + count++; + } + return spTable; +} + +void multiply_null_by_fuPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, NB, NS, siz_b, siz_s, ndim, nzCounts=0; + int *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2, *bir, *bjc; + double *pbDomain, *psDomain, *pbSize, *psSize, *spr, *bpr, value; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + siz_b = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + siz_s = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<siz_b; i++){ + NB *= (int)pbSize[i]; + } + NS = 1; + for(i=0; i<siz_s; i++){ + NS *= (int)psSize[i]; + } + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + + pTemp1 = mxCreateSparse(NB, 1, NB, mxREAL); + bpr = mxGetPr(pTemp1); + bir = mxGetIr(pTemp1); + bjc = mxGetJc(pTemp1); + bjc[0] = 0; + bjc[1] = NB; + + if(NS == 1){ + value = *spr; + for(i=0; i<NB; i++){ + bpr[i] = value; + bir[i] = i; + } + nzCounts = NB; + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + reset_nzmax(pTemp1, NB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp1); + return; + } + + if(NS == NB){ + for(i=0; i<NB; i++){ + if(spr[i] != 0){ + bpr[nzCounts] = spr[i]; + bir[nzCounts] = i; + nzCounts++; + } + } + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + reset_nzmax(pTemp1, NB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp1); + return; + } + + mask = malloc(siz_s * sizeof(int)); + count = 0; + for(i=0; i<siz_s; i++){ + for(j=0; j<siz_b; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + ndim = siz_b; + sx = (int *)malloc(sizeof(int)*ndim); + sy = (int *)malloc(sizeof(int)*ndim); + for(i=0; i<ndim; i++){ + sx[i] = (int)pbSize[i]; + sy[i] = 1; + } + for(i=0; i<count; i++){ + sy[mask[i]] = sx[mask[i]]; + } + + s = (int *)malloc(sizeof(int)*ndim); + *(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1; + subs = (int *)malloc(sizeof(int)*ndim); + cpsy2 = (int *)malloc(sizeof(int)*ndim); + for(i = 0; i < ndim; i++){ + subs[i] = 0; + s[i] = sx[i] - 1; + } + + for(i = 0; i < ndim-1; i++){ + cpsy[i+1] = cpsy[i]*sy[i]--; + cpsy2[i] = cpsy[i]*sy[i]; + } + cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]); + + for(j=0; j<NB; j++){ + if(*spr != 0){ + bpr[nzCounts] = *spr; + bir[nzCounts] = j; + nzCounts++; + } + for(i = 0; i < ndim; i++){ + if(subs[i] == s[i]){ + subs[i] = 0; + if(sy[i]) + spr -= cpsy2[i]; + } + else{ + subs[i]++; + if(sy[i]) + spr += cpsy[i]; + break; + } + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + reset_nzmax(pTemp1, NB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp1); + + free(sx); + free(sy); + free(s); + free(cpsy); + free(subs); + free(cpsy2); + free(mask); +} + +void multiply_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex, nzCounts=0; + int *samemask, *diffmask, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *sequence, *weight; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *spr; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + NS = 1; + for(i=0; i<sdim; i++){ + NS *= (int)psSize[i]; + } + ND = NB / NS; + + if(ND == 1){ + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp1 = mxGetField(smallPot, 0, "T"); + pTemp = mxDuplicateArray(pTemp1); + mxSetField(bigPot, 0, "T", pTemp); + return; + } + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + NZB = ND * NZS; + + diffdim = bdim - sdim; + sequence = malloc(NZB * 2 * sizeof(int)); + bigTable = malloc(NZB * sizeof(double)); + samemask = malloc(sdim * sizeof(int)); + diffmask = malloc(diffdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + weight = malloc(ND * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + count1 = 0; + for(i=0; i<bdim; i++){ + match = 0; + for(j=0; j<sdim; j++){ + if(pbDomain[i] == psDomain[j]){ + samemask[count] = i; + match = 1; + count++; + break; + } + } + if(match == 0){ + diffmask[count1] = i; + count1++; + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim); + for(i=0; i<NZS; i++){ + sindex = sir[i]; + ind_subv(sindex, sCumprod, sdim, ssubv); + temp = 0; + for(j=0; j<sdim; j++){ + temp += ssubv[j] * bCumprod[samemask[j]]; + } + for(j=0; j<ND; j++){ + bindex = weight[j] + temp; + bigTable[nzCounts] = spr[i]; + sequence[count] = bindex; + count++; + sequence[count] = nzCounts; + nzCounts++; + count++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + qsort(sequence, nzCounts, sizeof(int) * 2, compare); + pTemp = convert_ill_table_to_sparse(bigTable, sequence, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(sequence); + free(bigTable); + free(samemask); + free(diffmask); + free(bCumprod); + free(sCumprod); + free(weight); + free(ssubv); +} + +void multiply_spPot_by_fuPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, bindex, sindex, nzCounts=0; + int *mask, *bir, *bjc, *rir, *rjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, *rpr, value; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + + pTemp1 = mxCreateSparse(NB, 1, NZB, mxREAL); + rpr = mxGetPr(pTemp1); + rir = mxGetIr(pTemp1); + rjc = mxGetJc(pTemp1); + rjc[0] = 0; + rjc[1] = NZB; + + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + value = spr[sindex]; + if(value != 0){ + rpr[nzCounts] = bpr[i] * value; + rir[nzCounts] = bindex; + nzCounts++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + reset_nzmax(pTemp1, NZB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp1); + + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + +void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0; + int *mask, *result, *bir, *sir, *rir, *bjc, *sjc, *rjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, *rpr; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + pTemp1 = mxCreateSparse(NB, 1, NZB, mxREAL); + rpr = mxGetPr(pTemp1); + rir = mxGetIr(pTemp1); + rjc = mxGetJc(pTemp1); + rjc[0] = 0; + rjc[1] = NZB; + + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare); + if(result){ + position = result - sir; + rpr[nzCounts] = bpr[i] * spr[position]; + rir[nzCounts] = bindex; + nzCounts++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + reset_nzmax(pTemp1, NZB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp1); + + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ + int i, j, c, loop, nNodes, nCliques, ndomain, ns_num, nOnodes, dims[2]; + double *pClqs, *pr, *pt, *pSize, *eff_ns; + mxArray *pTemp, *pTemp1, *pStruct, *pCliques, *pBigpot, *pSmallpot; + const char *field_names[] = {"domain", "T", "sizes"}; + + nNodes = mxGetNumberOfElements(prhs[1]); + pCliques = mxGetField(prhs[0], 0, "cliques"); + nCliques = mxGetNumberOfElements(pCliques); + pTemp = mxGetField(prhs[0], 0, "actual_node_sizes"); + ns_num = mxGetNumberOfElements(pTemp); + pSize = mxGetPr(pTemp); + + eff_ns = (double *)malloc(ns_num * sizeof(double)); + for(i=0; i<ns_num; i++) eff_ns[i] = pSize[i]; + nOnodes = mxGetNumberOfElements(prhs[4]); + pr = mxGetPr(prhs[4]); + for(i=0; i<nOnodes; i++) eff_ns[(int)pr[i] - 1] = 1; + + plhs[0] = mxCreateCellArray(1, &nCliques); + for(i=0; i<nCliques; i++){ + pStruct = mxCreateStructMatrix(1, 1, 3, field_names); + mxSetCell(plhs[0], i, pStruct); + pTemp = mxGetCell(pCliques, i); + ndomain = mxGetNumberOfElements(pTemp); + pt = mxGetPr(pTemp); + pTemp1 = mxDuplicateArray(pTemp); + mxSetField(pStruct, 0, "domain", pTemp1); + + pTemp = mxCreateDoubleMatrix(1, ndomain, mxREAL); + mxSetField(pStruct, 0, "sizes", pTemp); + pr = mxGetPr(pTemp); + for(j=0; j<ndomain; j++){ + pr[j] = eff_ns[(int)pt[j]-1]; + } + } + + pClqs = mxGetPr(prhs[1]); + for(loop=0; loop<nNodes; loop++){ + c = (int)pClqs[loop] - 1; + pSmallpot = mxGetCell(prhs[2], loop); + pTemp = mxGetField(pSmallpot, 0, "T"); + pBigpot = mxGetCell(plhs[0], c); + pTemp1 = mxGetField(pBigpot, 0, "T"); + if(pTemp1){ + if(mxIsSparse(pTemp)) + multiply_spPot_by_spPot(pBigpot, pSmallpot); + else multiply_spPot_by_fuPot(pBigpot, pSmallpot); + } + else{ + if(mxIsSparse(pTemp)) + multiply_null_by_spPot(pBigpot, pSmallpot); + else multiply_null_by_fuPot(pBigpot, pSmallpot); + } + } + + free(eff_ns); + dims[0] = nCliques; + dims[1] = nCliques; + plhs[1] = mxCreateCellArray(2, dims); +} + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/jtree_sparse_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/jtree_sparse_inf_engine.m new file mode 100644 index 00000000..49dcd69f --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/jtree_sparse_inf_engine.m @@ -0,0 +1,126 @@ +function engine = jtree_sparse_inf_engine(bnet, varargin) +% JTREE_SPARSE_INF_ENGINE Junction tree inference engine when CPTs and Potentials are sparse +% engine = jtree_sparse_inf_engine(bnet, ...) +% It differs from jtree_inf_engine with all CPTs and potentials are 1D sparse arrays. +% +% 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 }; + +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}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + +engine = init_fields; +engine = class(engine, 'jtree_sparse_inf_engine', inf_engine(bnet)); + +onodes = bnet.observed; +%[engine.jtree, dummy, engine.cliques, B, w] = 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. +engine.root_clq = clq_containing_nodes(engine, root); +if engine.root_clq <= 0 + error(['no clique contains ' num2str(root)]); +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 + +ns = bnet.node_sizes; +engine.actual_node_sizes = ns; + + +%%%%%%%% + +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 = []; +engine.actual_node_sizes = []; + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/marginal_family.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/marginal_family.m new file mode 100644 index 00000000..eff60ca2 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_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_sparse_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..6413172c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_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_sparse_inf_engine/old/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Entries new file mode 100644 index 00000000..f74fd729 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Entries @@ -0,0 +1,6 @@ +/collect_evidence.c/1.1.1.1/Wed May 29 15:59:56 2002// +/distribute_evidence.c/1.1.1.1/Wed May 29 15:59:56 2002// +/init_pot.c/1.1.1.1/Wed May 29 15:59:56 2002// +/init_pot1.c/1.1.1.1/Wed May 29 15:59:56 2002// +/init_pot1.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Repository new file mode 100644 index 00000000..eb323e83 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_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_sparse_inf_engine/old/collect_evidence.c b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/collect_evidence.c new file mode 100644 index 00000000..3e6d35c7 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/collect_evidence.c @@ -0,0 +1,635 @@ +/* C mex for collect_evidence.c in @jtree_sparse_inf_engine directory */ +/* File enter_evidence.m in directory @jtree_sparse_inf_engine call it*/ + +/******************************************/ +/* collect_evidence has 3 input & 2 output*/ +/* engine */ +/* clpot */ +/* seppot */ +/* */ +/* clpot */ +/* seppot */ +/******************************************/ + +#include <math.h> +#include <search.h> +#include "mex.h" + +int compare(const void* src1, const void* src2){ + int i1 = *(int*)src1 ; + int i2 = *(int*)src2 ; + return i1-i2 ; +} + +void ind_subv(int index, const int *cumprod, int n, int *bsubv){ + int i; + + for (i = n-1; i >= 0; i--) { + bsubv[i] = ((int)floor(index / cumprod[i])); + index = index % cumprod[i]; + } +} + +int subv_ind(const int n, const int *cumprod, const int *subv){ + int i, index=0; + + for(i=0; i<n; i++){ + index += subv[i] * cumprod[i]; + } + return index; +} + +void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){ + int i, j; + int *eff_cumprod, *subv, *diffsize, *diff_cumprod; + + subv = malloc(diffdim * sizeof(int)); + eff_cumprod = malloc(diffdim * sizeof(int)); + diffsize = malloc(diffdim * sizeof(int)); + diff_cumprod = malloc(diffdim * sizeof(int)); + for(i=0; i<diffdim; i++){ + eff_cumprod[i] = bCumprod[dmask[i]]; + diffsize[i] = (int)pbSize[dmask[i]]; + } + diff_cumprod[0] = 1; + for(i=0; i<diffdim-1; i++){ + diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i]; + } + for(i=0; i<ND; i++){ + ind_subv(i, diff_cumprod, diffdim, subv); + weight[i] = 0; + for(j=0; j<diffdim; j++){ + weight[i] += eff_cumprod[j] * subv[j]; + } + } + free(eff_cumprod); + free(subv); + free(diffsize); + free(diff_cumprod); +} + +mxArray* convert_table_to_sparse(const double *bT, const int *index, const int nzCounts, const int N){ + mxArray *spTable; + int i, *irs, *jcs; + double *sr; + + spTable = mxCreateSparse(N, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + sr[i] = bT[i]; + irs[i] = index[i]; + } + return spTable; +} + +mxArray* convert_ill_table_to_sparse(const double *Table, const int *sequence, const int nzCounts, const int N){ + mxArray *spTable; + int i, temp, *irs, *jcs, count=0; + double *sr; + + spTable = mxCreateSparse(N, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + irs[i] = sequence[count]; + count++; + temp = sequence[count]; + sr[i] = Table[temp]; + count++; + } + return spTable; +} + +void multiply_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex, nzCounts=0; + int *samemask, *diffmask, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *sequence, *weight; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *spr, *bpr; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + if(sdim == 0){ + pTemp = mxCreateSparse(NB, 1, NB, mxREAL); + mxSetField(bigPot, 0, "T", pTemp); + bpr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + sjc[0] = 0; + sjc[1] = NB; + for(i=0; i<NB; i++){ + bpr[i] = *spr; + sir[i] = i; + } + return; + } + + NS = 1; + for(i=0; i<sdim; i++){ + NS *= (int)psSize[i]; + } + ND = NB / NS; + + if(ND == 1){ + pTemp1 = mxGetField(smallPot, 0, "T"); + pTemp = mxDuplicateArray(pTemp1); + mxSetField(bigPot, 0, "T", pTemp); + return; + } + + + NZB = ND * NZS; + + diffdim = bdim - sdim; + sequence = malloc(NZB * 2 * sizeof(int)); + bigTable = malloc(NZB * sizeof(double)); + samemask = malloc(sdim * sizeof(int)); + diffmask = malloc(diffdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + weight = malloc(ND * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + count1 = 0; + for(i=0; i<bdim; i++){ + match = 0; + for(j=0; j<sdim; j++){ + if(pbDomain[i] == psDomain[j]){ + samemask[count] = i; + match = 1; + count++; + break; + } + } + if(match == 0){ + diffmask[count1] = i; + count1++; + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim); + for(i=0; i<NZS; i++){ + sindex = sir[i]; + ind_subv(sindex, sCumprod, sdim, ssubv); + temp = 0; + for(j=0; j<sdim; j++){ + temp += ssubv[j] * bCumprod[samemask[j]]; + } + for(j=0; j<ND; j++){ + bindex = weight[j] + temp; + bigTable[nzCounts] = spr[i]; + sequence[count] = bindex; + count++; + sequence[count] = nzCounts; + nzCounts++; + count++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + qsort(sequence, nzCounts, sizeof(int) * 2, compare); + pTemp = convert_ill_table_to_sparse(bigTable, sequence, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(sequence); + free(bigTable); + free(samemask); + free(diffmask); + free(bCumprod); + free(sCumprod); + free(weight); + free(ssubv); +} + +void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0; + int *mask, *index, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value; + mxArray *pTemp; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + if(sdim == 0){ + for(i=0; i<NZB; i++){ + bpr[i] *= *spr; + } + return; + } + + bigTable = malloc(NZB * sizeof(double)); + index = malloc(NZB * sizeof(double)); + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + for(i=0; i<NZB; i++){ + bigTable[i] = 0; + } + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + value = bpr[i]; + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare); + if(result){ + position = result - sir; + value *= spr[position]; + bigTable[nzCounts] = value; + index[nzCounts] = bindex; + nzCounts++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(bigTable); + free(index); + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + +mxArray* marginal_null_to_spPot(const mxArray *bigPot, const mxArray *sDomain, const int maximize){ + int i, j, count, bdim, sdim, NB, NS, ND; + int *mask, *sir, *sjc; + double *pbDomain, *psDomain, *pbSize, *psSize, *spr; + mxArray *pTemp, *smallPot; + const char *field_names[] = {"domain", "T", "sizes"}; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + psDomain = mxGetPr(sDomain); + sdim = mxGetNumberOfElements(sDomain); + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + + smallPot = mxCreateStructMatrix(1, 1, 3, field_names); + pTemp = mxDuplicateArray(sDomain); + mxSetField(smallPot, 0, "domain", pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + if(sdim == 0){ + pTemp = mxCreateSparse(1, 1, 1, mxREAL); + mxSetField(smallPot, 0, "T", pTemp); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + *spr = 0; + *sir = 0; + sjc[0] = 0; + sjc[1] = 1; + if(maximize) *spr = 1; + else *spr = NB; + + pTemp = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(pTemp) = 1; + mxSetField(smallPot, 0, "sizes", pTemp); + return smallPot; + } + + mask = malloc(sdim * sizeof(int)); + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + pTemp = mxCreateDoubleMatrix(1, count, mxREAL); + psSize = mxGetPr(pTemp); + NS = 1; + for(i=0; i<count; i++){ + psSize[i] = pbSize[mask[i]]; + NS *= (int)psSize[i]; + } + mxSetField(smallPot, 0, "sizes", pTemp); + + ND = NB / NS; + + pTemp = mxCreateSparse(NS, 1, NS, mxREAL); + mxSetField(smallPot, 0, "T", pTemp); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + if(maximize){ + for(i=0; i<NS; i++){ + spr[i] = 1; + sir[i] = i; + } + } + else{ + for(i=0; i<NS; i++){ + spr[i] = ND; + sir[i] = i; + } + } + sjc[0] = 0; + sjc[1] = NS; + + free(mask); + return smallPot; +} + +mxArray* marginal_spPot_to_spPot(const mxArray *bigPot, const mxArray *sDomain, const int maximize){ + int i, j, count, bdim, sdim, NB, NS, NZB, position, bindex, sindex, nzCounts=0; + int *mask, *sequence, *result, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *sTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr; + mxArray *pTemp, *smallPot; + const char *field_names[] = {"domain", "T", "sizes"}; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + psDomain = mxGetPr(sDomain); + sdim = mxGetNumberOfElements(sDomain); + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + smallPot = mxCreateStructMatrix(1, 1, 3, field_names); + pTemp = mxDuplicateArray(sDomain); + mxSetField(smallPot, 0, "domain", pTemp); + + if(sdim == 0){ + pTemp = mxCreateSparse(1, 1, 1, mxREAL); + mxSetField(smallPot, 0, "T", pTemp); + spr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + *spr = 0; + *bir = 0; + bjc[0] = 0; + bjc[1] = 1; + if(maximize){ + for(i=0; i<NZB; i++){ + *spr = (*spr < bpr[i])? bpr[i] : *spr; + } + } + else{ + for(i=0; i<NZB; i++){ + *spr += bpr[i]; + } + } + + pTemp = mxCreateDoubleMatrix(1, 1, mxREAL); + *mxGetPr(pTemp) = 1; + mxSetField(smallPot, 0, "sizes", pTemp); + return smallPot; + } + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + mask = malloc(sdim * sizeof(int)); + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + pTemp = mxCreateDoubleMatrix(1, count, mxREAL); + psSize = mxGetPr(pTemp); + NS = 1; + for(i=0; i<count; i++){ + psSize[i] = pbSize[mask[i]]; + NS *= (int)psSize[i]; + } + mxSetField(smallPot, 0, "sizes", pTemp); + + + sTable = malloc(NZB * sizeof(double)); + sequence = malloc(NZB * 2 * sizeof(double)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + for(i=0; i<NZB; i++)sTable[i] = 0; + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sequence, nzCounts, sizeof(int)*2, compare); + if(result){ + position = (result - sequence) / 2; + if(maximize) + sTable[position] = (sTable[position] < bpr[i]) ? bpr[i] : sTable[position]; + else sTable[position] += bpr[i]; + } + else { + if(maximize) + sTable[nzCounts] = (sTable[nzCounts] < bpr[i]) ? bpr[i] : sTable[nzCounts]; + else sTable[nzCounts] += bpr[i]; + sequence[count] = sindex; + count++; + sequence[count] = nzCounts; + nzCounts++; + count++; + } + } + + qsort(sequence, nzCounts, sizeof(int) * 2, compare); + pTemp = convert_ill_table_to_sparse(sTable, sequence, nzCounts, NS); + mxSetField(smallPot, 0, "T", pTemp); + + free(sTable); + free(sequence); + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); + + return smallPot; +} + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ + int i, n, p, np, pn, loop, loops, nCliques, temp, maximize; + int *collect_order; + double *pr, *pr1; + mxArray *pTemp, *pTemp1, *pPostP, *pClpot, *pSeppot, *pSeparator; + + pTemp = mxGetField(prhs[0], 0, "cliques"); + nCliques = mxGetNumberOfElements(pTemp); + loops = nCliques - 1; + pTemp = mxGetField(prhs[0], 0, "maximize"); + maximize = (int)mxGetScalar(pTemp); + pSeparator = mxGetField(prhs[0], 0, "separator"); + + collect_order = malloc(2 * loops * sizeof(int)); + + pTemp = mxGetField(prhs[0], 0, "postorder"); + pr = mxGetPr(pTemp); + pPostP = mxGetField(prhs[0], 0, "postorder_parents"); + for(i=0; i<loops; i++){ + temp = (int)pr[i] - 1; + pTemp = mxGetCell(pPostP, temp); + pr1 = mxGetPr(pTemp); + collect_order[i] = (int)pr1[0] - 1; + collect_order[i+loops] = temp; + } + + plhs[0] = mxDuplicateArray(prhs[1]); + plhs[1] = mxDuplicateArray(prhs[2]); + + for(loop=0; loop<loops; loop++){ + p = collect_order[loop]; + n = collect_order[loop+loops]; + np = p * nCliques + n; + pn = n * nCliques + p; + pClpot = mxGetCell(plhs[0], n); + pTemp1 = mxGetField(pClpot, 0, "T"); + pTemp = mxGetCell(pSeparator, pn); + if(pTemp1) + pSeppot = marginal_spPot_to_spPot(pClpot, pTemp, maximize); + else pSeppot = marginal_null_to_spPot(pClpot, pTemp, maximize); + mxSetCell(plhs[1], pn, pSeppot); + + pClpot = mxGetCell(plhs[0], p); + pTemp1 = mxGetField(pClpot, 0, "T"); + if(pTemp1) + multiply_spPot_by_spPot(pClpot, pSeppot); + else multiply_null_by_spPot(pClpot, pSeppot); + } + free(collect_order); +} + + + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/distribute_evidence.c b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/distribute_evidence.c new file mode 100644 index 00000000..3d8ec66b --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/distribute_evidence.c @@ -0,0 +1,613 @@ +/* C mex for distribute_evidence.c in @jtree_sparse_inf_engine directory*/ +/* File enter_evidence.m in directory @jtree_sparse_inf_engine call it */ + +/*********************************************/ +/* distribute_evidence has 3 input & 2 output*/ +/* engine */ +/* clpot */ +/* seppot */ +/* */ +/* clpot */ +/* seppot */ +/*********************************************/ + +#include "mex.h" + +#include <math.h> +#include <search.h> +#include "mex.h" + +int compare(const void* src1, const void* src2){ + int i1 = *(int*)src1 ; + int i2 = *(int*)src2 ; + return i1-i2 ; +} + +void ind_subv(int index, const int *cumprod, int n, int *bsubv){ + int i; + + for (i = n-1; i >= 0; i--) { + bsubv[i] = ((int)floor(index / cumprod[i])); + index = index % cumprod[i]; + } +} + +int subv_ind(const int n, const int *cumprod, const int *subv){ + int i, index=0; + + for(i=0; i<n; i++){ + index += subv[i] * cumprod[i]; + } + return index; +} + +void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){ + int i, j; + int *eff_cumprod, *subv, *diffsize, *diff_cumprod; + + subv = malloc(diffdim * sizeof(int)); + eff_cumprod = malloc(diffdim * sizeof(int)); + diffsize = malloc(diffdim * sizeof(int)); + diff_cumprod = malloc(diffdim * sizeof(int)); + for(i=0; i<diffdim; i++){ + eff_cumprod[i] = bCumprod[dmask[i]]; + diffsize[i] = (int)pbSize[dmask[i]]; + } + diff_cumprod[0] = 1; + for(i=0; i<diffdim-1; i++){ + diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i]; + } + for(i=0; i<ND; i++){ + ind_subv(i, diff_cumprod, diffdim, subv); + weight[i] = 0; + for(j=0; j<diffdim; j++){ + weight[i] += eff_cumprod[j] * subv[j]; + } + } + free(eff_cumprod); + free(subv); + free(diffsize); + free(diff_cumprod); +} + +mxArray* convert_table_to_sparse(const double *bT, const int *index, const int nzCounts, const int N){ + mxArray *spTable; + int i, *irs, *jcs; + double *sr; + + spTable = mxCreateSparse(N, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + sr[i] = bT[i]; + irs[i] = index[i]; + } + return spTable; +} + +mxArray* convert_ill_table_to_sparse(const double *Table, const int *sequence, const int nzCounts, const int N){ + mxArray *spTable; + int i, temp, *irs, *jcs, count=0; + double *sr; + + spTable = mxCreateSparse(N, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + irs[i] = sequence[count]; + count++; + temp = sequence[count]; + sr[i] = Table[temp]; + count++; + } + return spTable; +} + +void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0; + int *mask, *index, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value; + mxArray *pTemp; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + if(sdim == 0){ + for(i=0; i<NZB; i++){ + bpr[i] *= *spr; + } + return; + } + + bigTable = malloc(NZB * sizeof(double)); + index = malloc(NZB * sizeof(double)); + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + value = bpr[i]; + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare); + if(result){ + position = result - sir; + value *= spr[position]; + bigTable[nzCounts] = value; + index[nzCounts] = bindex; + nzCounts++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(bigTable); + free(index); + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + +void marginal_spPot_to_spPot(const mxArray *bigPot, mxArray *smallPot, const int maximize){ + int i, j, count, bdim, sdim, NB, NS, NZB, position, bindex, sindex, nzCounts=0; + int *mask, *sequence, *result, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *sTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr; + mxArray *pTemp; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + NS = 1; + for(i=0; i<sdim; i++){ + NS *= (int)psSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + if(sdim == 0){ + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + *spr = 0; + if(maximize){ + for(i=0; i<NZB; i++){ + *spr = (*spr < bpr[i])? bpr[i] : *spr; + } + } + else{ + for(i=0; i<NZB; i++){ + *spr += bpr[i]; + } + } + return; + } + + mask = malloc(sdim * sizeof(int)); + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + + sTable = malloc(NZB * sizeof(double)); + sequence = malloc(NZB * 2 * sizeof(double)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + for(i=0; i<NZB; i++){ + sTable[i] = 0; + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sequence, nzCounts, sizeof(int)*2, compare); + if(result){ + position = (result - sequence) / 2; + if(maximize) + sTable[position] = (sTable[position] < bpr[i]) ? bpr[i] : sTable[position]; + else sTable[position] += bpr[i]; + } + else { + if(maximize) + sTable[nzCounts] = (sTable[nzCounts] < bpr[i]) ? bpr[i] : sTable[nzCounts]; + else sTable[nzCounts] += bpr[i]; + sequence[count] = sindex; + count++; + sequence[count] = nzCounts; + nzCounts++; + count++; + } + } + + pTemp = mxGetField(smallPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + qsort(sequence, nzCounts, sizeof(int) * 2, compare); + pTemp = convert_ill_table_to_sparse(sTable, sequence, nzCounts, NS); + mxSetField(smallPot, 0, "T", pTemp); + + free(sTable); + free(sequence); + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + +void divide_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex; + int *samemask, *diffmask, *rir, *rjc, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *weight; + double *pbDomain, *psDomain, *pbSize, *psSize, *rpr, *spr, value; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + if(sdim == 0){ + pTemp = mxCreateSparse(NB, 1, NB, mxREAL); + mxSetField(bigPot, 0, "T", pTemp); + rpr = mxGetPr(pTemp); + rir = mxGetIr(pTemp); + rjc = mxGetJc(pTemp); + rjc[0] = 0; + rjc[1] = NB; + value = *spr; + if(value == 0) value = 1; + for(i=0; i<NB; i++){ + rpr[i] = 1 / value; + rir[i] = i; + } + return; + } + + NS = 1; + for(i=0; i<sdim; i++){ + NS *= (int)psSize[i]; + } + ND = NB / NS; + + + pTemp = mxCreateSparse(NB, 1, NB, mxREAL); + rpr = mxGetPr(pTemp); + rir = mxGetIr(pTemp); + rjc = mxGetJc(pTemp); + rjc[0] = 0; + rjc[1] = NB; + for(i=0; i<NB; i++){ + rpr[i] = 1; + rir[i] = i; + } + + NZB = ND * NZS; + + diffdim = bdim - sdim; + samemask = malloc(sdim * sizeof(int)); + diffmask = malloc(diffdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + weight = malloc(ND * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + count1 = 0; + for(i=0; i<bdim; i++){ + match = 0; + for(j=0; j<sdim; j++){ + if(pbDomain[i] == psDomain[j]){ + samemask[count] = i; + match = 1; + count++; + break; + } + } + if(match == 0){ + diffmask[count1] = i; + count1++; + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim); + for(i=0; i<NZS; i++){ + sindex = sir[i]; + ind_subv(sindex, sCumprod, sdim, ssubv); + temp = 0; + for(j=0; j<sdim; j++){ + temp += ssubv[j] * bCumprod[samemask[j]]; + } + for(j=0; j<ND; j++){ + bindex = weight[j] + temp; + rpr[bindex] = 1 / (spr[i]); + } + } + + pTemp1 = mxGetField(bigPot, 0, "T"); + if(pTemp1)mxDestroyArray(pTemp1); + mxSetField(bigPot, 0, "T", pTemp); + + free(samemask); + free(diffmask); + free(bCumprod); + free(sCumprod); + free(weight); + free(ssubv); +} + +void divide_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex; + int *mask, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp1 = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp1); + bir = mxGetIr(pTemp1); + bjc = mxGetJc(pTemp1); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + if(sdim == 0){ + value = *spr; + if(value == 0)value = 1; + for(i=0; i<NZB; i++){ + bpr[i] /= value; + } + return; + } + + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare); + if(result){ + position = result - sir; + bpr[i] /= spr[position]; + } + } + + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ + int i, j, loop, loops, nCliques, temp, count, parent, child, maximize, *distribute_order; + double *pr, *pr1; + mxArray *pTemp, *pPreCh, *pClpot, *pSeppot; + + pTemp = mxGetField(prhs[0], 0, "cliques"); + nCliques = mxGetNumberOfElements(pTemp); + loops = nCliques - 1; + pTemp = mxGetField(prhs[0], 0, "maximize"); + maximize = (int)mxGetScalar(pTemp); + + distribute_order = malloc(2 * loops * sizeof(int)); + pTemp = mxGetField(prhs[0], 0, "preorder"); + pr = mxGetPr(pTemp); + pPreCh = mxGetField(prhs[0], 0, "preorder_children"); + count = 0; + for(i=0; i<nCliques; i++){ + temp = (int)pr[i] - 1; + pTemp = mxGetCell(pPreCh, temp); + pr1 = mxGetPr(pTemp); + loop = mxGetNumberOfElements(pTemp); + for(j=0; j<loop; j++){ + distribute_order[count] = temp; + distribute_order[count + loops] = (int)pr1[j] - 1; + count++; + } + } + + plhs[0] = mxDuplicateArray(prhs[1]); + plhs[1] = mxDuplicateArray(prhs[2]); + + for(loop=0; loop<loops; loop++){ + parent = distribute_order[loop]; + child = distribute_order[loop+loops]; + i = nCliques * child + parent; + pClpot = mxGetCell(plhs[0], child); + pTemp = mxGetField(pClpot, 0, "T"); + pSeppot = mxGetCell(plhs[1], i); + if(pTemp) + divide_spPot_by_spPot(pClpot, pSeppot); + else divide_null_by_spPot(pClpot, pSeppot); + + pClpot = mxGetCell(plhs[0], parent); + marginal_spPot_to_spPot(pClpot, pSeppot, maximize); + mxSetCell(plhs[1], i, pSeppot); + + pClpot = mxGetCell(plhs[0], child); + multiply_spPot_by_spPot(pClpot, pSeppot); + } + free(distribute_order); +} diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot.c b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot.c new file mode 100644 index 00000000..5d0ed8a3 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot.c @@ -0,0 +1,637 @@ +/* C mex init_pot for in @jtree_sparse_inf_engine directory */ +/* The file enter_evidence.m in directory @jtree_sparse_inf_engine call it*/ + +/**************************************/ +/* init_pot.c has 6 input & 2 output */ +/* engine */ +/* clqs */ +/* pots */ +/* pot_type */ +/* onodes */ +/* ndx */ +/* */ +/* clpot */ +/* seppot */ +/**************************************/ +#include <math.h> +#include <search.h> +#include "mex.h" + +int compare(const void* src1, const void* src2){ + int i1 = *(int*)src1 ; + int i2 = *(int*)src2 ; + return i1-i2 ; +} + +void ind_subv(int index, const int *cumprod, int n, int *bsubv){ + int i; + + for (i = n-1; i >= 0; i--) { + bsubv[i] = ((int)floor(index / cumprod[i])); + index = index % cumprod[i]; + } +} + +int subv_ind(const int n, const int *cumprod, const int *subv){ + int i, index=0; + + for(i=0; i<n; i++){ + index += subv[i] * cumprod[i]; + } + return index; +} + +void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){ + int i, j; + int *eff_cumprod, *subv, *diffsize, *diff_cumprod; + + subv = malloc(diffdim * sizeof(int)); + eff_cumprod = malloc(diffdim * sizeof(int)); + diffsize = malloc(diffdim * sizeof(int)); + diff_cumprod = malloc(diffdim * sizeof(int)); + for(i=0; i<diffdim; i++){ + eff_cumprod[i] = bCumprod[dmask[i]]; + diffsize[i] = (int)pbSize[dmask[i]]; + } + diff_cumprod[0] = 1; + for(i=0; i<diffdim-1; i++){ + diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i]; + } + for(i=0; i<ND; i++){ + ind_subv(i, diff_cumprod, diffdim, subv); + weight[i] = 0; + for(j=0; j<diffdim; j++){ + weight[i] += eff_cumprod[j] * subv[j]; + } + } + free(eff_cumprod); + free(subv); + free(diffsize); + free(diff_cumprod); +} + +mxArray* convert_to_sparse(const double *table, const int NB, const int counts){ + mxArray *spTable; + int i, k, *ir, *jc; + double *sr; + + spTable = mxCreateSparse(NB, 1, counts, mxREAL); + sr = mxGetPr(spTable); + ir = mxGetIr(spTable); + jc = mxGetJc(spTable); + + k = 0; + jc[0] = 0; + jc[1] = counts; + for(i=0; i<NB; i++){ + if(table[i] != 0.0){ + sr[k] = table[i]; + ir[k] = i; + k++; + } + } + + return spTable; +} + +mxArray* convert_table_to_sparse(const double *bT, const int *index, const int nzCounts, const int NB){ + mxArray *spTable; + int i, *irs, *jcs; + double *sr; + + spTable = mxCreateSparse(NB, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + sr[i] = bT[i]; + irs[i] = index[i]; + } + return spTable; +} + +mxArray* convert_ill_table_to_sparse(const double *bigTable, const int *sequence, const int nzCounts, const int NB){ + mxArray *spTable; + int i, temp, *irs, *jcs, count=0; + double *sr; + + spTable = mxCreateSparse(NB, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + irs[i] = sequence[count]; + count++; + temp = sequence[count]; + sr[i] = bigTable[temp]; + count++; + } + return spTable; +} + +void multiply_null_by_fuPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, NB, NS, siz_b, siz_s, ndim, nzCounts=0; + int *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2, *jc; + double *pbDomain, *psDomain, *pbSize, *psSize, *bTable, *sTable, value; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + siz_b = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + siz_s = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<siz_b; i++){ + NB *= (int)pbSize[i]; + } + NS = 1; + for(i=0; i<siz_s; i++){ + NS *= (int)psSize[i]; + } + + pTemp = mxGetField(smallPot, 0, "T"); + sTable = mxGetPr(pTemp); + bTable = malloc(NB * sizeof(double)); + for(i=0; i<NB; i++){ + bTable[i] = 0; + } + + if(NS == 1){ + value = *sTable; + for(i=0; i<NB; i++){ + bTable[i] = value; + } + nzCounts = NB; + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp = convert_to_sparse(bTable, NB, NB); + mxSetField(bigPot, 0, "T", pTemp); + free(bTable); + return; + } + + if(NS == NB){ + for(i=0; i<NB; i++){ + bTable[i] = sTable[i]; + if(sTable[i] != 0) nzCounts++; + } + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp = convert_to_sparse(bTable, NB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp); + free(bTable); + return; + } + + mask = malloc(siz_s * sizeof(int)); + count = 0; + for(i=0; i<siz_s; i++){ + for(j=0; j<siz_b; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + ndim = siz_b; + sx = (int *)malloc(sizeof(int)*ndim); + sy = (int *)malloc(sizeof(int)*ndim); + for(i=0; i<ndim; i++){ + sx[i] = (int)pbSize[i]; + sy[i] = 1; + } + for(i=0; i<count; i++){ + sy[mask[i]] = sx[mask[i]]; + } + + s = (int *)malloc(sizeof(int)*ndim); + *(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1; + subs = (int *)malloc(sizeof(int)*ndim); + cpsy2 = (int *)malloc(sizeof(int)*ndim); + for(i = 0; i < ndim; i++){ + subs[i] = 0; + s[i] = sx[i] - 1; + } + + for(i = 0; i < ndim-1; i++){ + cpsy[i+1] = cpsy[i]*sy[i]--; + cpsy2[i] = cpsy[i]*sy[i]; + } + cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]); + + for(j=0; j<NB; j++){ + bTable[j] = *sTable; + if(*sTable != 0.0) nzCounts++; + for(i = 0; i < ndim; i++){ + if(subs[i] == s[i]){ + subs[i] = 0; + if(sy[i]) + sTable -= cpsy2[i]; + } + else{ + subs[i]++; + if(sy[i]) + sTable += cpsy[i]; + break; + } + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp = convert_to_sparse(bTable, NB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp); + pTemp1 = mxGetField(bigPot, 0, "T"); + jc = mxGetJc(pTemp1); + + free(sx); + free(sy); + free(s); + free(cpsy); + free(subs); + free(cpsy2); + free(mask); + free(bTable); +} + +void multiply_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex, nzCounts=0; + int *samemask, *diffmask, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *sequence, *weight; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *spr; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + NS = 1; + for(i=0; i<sdim; i++){ + NS *= (int)psSize[i]; + } + ND = NB / NS; + + if(ND == 1){ + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp1 = mxGetField(smallPot, 0, "T"); + pTemp = mxDuplicateArray(pTemp1); + mxSetField(bigPot, 0, "T", pTemp); + return; + } + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + NZB = ND * NZS; + + diffdim = bdim - sdim; + sequence = malloc(NZB * 2 * sizeof(int)); + bigTable = malloc(NZB * sizeof(double)); + samemask = malloc(sdim * sizeof(int)); + diffmask = malloc(diffdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + weight = malloc(ND * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + count1 = 0; + for(i=0; i<bdim; i++){ + match = 0; + for(j=0; j<sdim; j++){ + if(pbDomain[i] == psDomain[j]){ + samemask[count] = i; + match = 1; + count++; + break; + } + } + if(match == 0){ + diffmask[count1] = i; + count1++; + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim); + for(i=0; i<NZS; i++){ + sindex = sir[i]; + ind_subv(sindex, sCumprod, sdim, ssubv); + temp = 0; + for(j=0; j<sdim; j++){ + temp += ssubv[j] * bCumprod[samemask[j]]; + } + for(j=0; j<ND; j++){ + bindex = weight[j] + temp; + bigTable[nzCounts] = spr[i]; + sequence[count] = bindex; + count++; + sequence[count] = nzCounts; + nzCounts++; + count++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + qsort(sequence, nzCounts, sizeof(int) * 2, compare); + pTemp = convert_ill_table_to_sparse(bigTable, sequence, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(sequence); + free(bigTable); + free(samemask); + free(diffmask); + free(bCumprod); + free(sCumprod); + free(weight); + free(ssubv); +} + +void multiply_spPot_by_fuPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, bindex, sindex, nzCounts=0; + int *mask, *index, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value; + mxArray *pTemp; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + + bigTable = malloc(NZB * sizeof(double)); + index = malloc(NZB * sizeof(double)); + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + for(i=0; i<NZB; i++){ + bigTable[i] = 0; + } + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + value = spr[sindex]; + if(value != 0){ + bigTable[nzCounts] = bpr[i] * value; + index[nzCounts] = bindex; + nzCounts++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(bigTable); + free(index); + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + +void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0; + int *mask, *index, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value; + mxArray *pTemp; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + bigTable = malloc(NZB * sizeof(double)); + index = malloc(NZB * sizeof(double)); + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + for(i=0; i<NZB; i++){ + bigTable[i] = 0; + } + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + value = bpr[i]; + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare); + if(result){ + position = result - sir; + value *= spr[position]; + bigTable[nzCounts] = value; + index[nzCounts] = bindex; + nzCounts++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(bigTable); + free(index); + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ + int i, j, c, loop, nNodes, nCliques, ndomain, dims[2]; + double *pClqs, *pr, *pt, *pSize; + mxArray *pTemp, *pTemp1, *pStruct, *pCliques, *pBigpot, *pSmallpot; + const char *field_names[] = {"domain", "T", "sizes"}; + + nNodes = mxGetNumberOfElements(prhs[1]); + pCliques = mxGetField(prhs[0], 0, "cliques"); + nCliques = mxGetNumberOfElements(pCliques); + pTemp = mxGetField(prhs[0], 0, "eff_node_sizes"); + pSize = mxGetPr(pTemp); + + plhs[0] = mxCreateCellArray(1, &nCliques); + for(i=0; i<nCliques; i++){ + pStruct = mxCreateStructMatrix(1, 1, 3, field_names); + mxSetCell(plhs[0], i, pStruct); + pTemp = mxGetCell(pCliques, i); + ndomain = mxGetNumberOfElements(pTemp); + pt = mxGetPr(pTemp); + pTemp1 = mxDuplicateArray(pTemp); + mxSetField(pStruct, 0, "domain", pTemp1); + + pTemp = mxCreateDoubleMatrix(1, ndomain, mxREAL); + mxSetField(pStruct, 0, "sizes", pTemp); + pr = mxGetPr(pTemp); + for(j=0; j<ndomain; j++){ + pr[j] = pSize[(int)pt[j]-1]; + } + } + + pClqs = mxGetPr(prhs[1]); + for(loop=0; loop<nNodes; loop++){ + c = (int)pClqs[loop] - 1; + pSmallpot = mxGetCell(prhs[2], loop); + pTemp = mxGetField(pSmallpot, 0, "T"); + pBigpot = mxGetCell(plhs[0], c); + pTemp1 = mxGetField(pBigpot, 0, "T"); + if(pTemp1){ + if(mxIsSparse(pTemp)) + multiply_spPot_by_spPot(pBigpot, pSmallpot); + else multiply_spPot_by_fuPot(pBigpot, pSmallpot); + } + else{ + if(mxIsSparse(pTemp)) + multiply_null_by_spPot(pBigpot, pSmallpot); + else multiply_null_by_fuPot(pBigpot, pSmallpot); + } + } + + dims[0] = nCliques; + dims[1] = nCliques; + plhs[1] = mxCreateCellArray(2, dims); +} + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot1.c b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot1.c new file mode 100644 index 00000000..b3a6a66d --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot1.c @@ -0,0 +1,636 @@ +/* C mex init_pot for in @jtree_sparse_inf_engine directory */ +/* The file enter_evidence.m in directory @jtree_sparse_inf_engine call it*/ + +/**************************************/ +/* init_pot.c has 6 input & 2 output */ +/* engine */ +/* clqs */ +/* pots */ +/* pot_type */ +/* onodes */ +/* ndx */ +/* */ +/* clpot */ +/* seppot */ +/**************************************/ +#include <math.h> +#include <search.h> +#include "mex.h" + +int compare(const void* src1, const void* src2){ + int i1 = *(int*)src1 ; + int i2 = *(int*)src2 ; + return i1-i2 ; +} + +void ind_subv(int index, const int *cumprod, int n, int *bsubv){ + int i; + + for (i = n-1; i >= 0; i--) { + bsubv[i] = ((int)floor(index / cumprod[i])); + index = index % cumprod[i]; + } +} + +int subv_ind(const int n, const int *cumprod, const int *subv){ + int i, index=0; + + for(i=0; i<n; i++){ + index += subv[i] * cumprod[i]; + } + return index; +} + +void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){ + int i, j; + int *eff_cumprod, *subv, *diffsize, *diff_cumprod; + + subv = malloc(diffdim * sizeof(int)); + eff_cumprod = malloc(diffdim * sizeof(int)); + diffsize = malloc(diffdim * sizeof(int)); + diff_cumprod = malloc(diffdim * sizeof(int)); + for(i=0; i<diffdim; i++){ + eff_cumprod[i] = bCumprod[dmask[i]]; + diffsize[i] = (int)pbSize[dmask[i]]; + } + diff_cumprod[0] = 1; + for(i=0; i<diffdim-1; i++){ + diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i]; + } + for(i=0; i<ND; i++){ + ind_subv(i, diff_cumprod, diffdim, subv); + weight[i] = 0; + for(j=0; j<diffdim; j++){ + weight[i] += eff_cumprod[j] * subv[j]; + } + } + free(eff_cumprod); + free(subv); + free(diffsize); + free(diff_cumprod); +} + +void reset_nzmax(mxArray *spArray, const int old_nzmax, const int new_nzmax){ + double *ptr; + void *newptr; + int *ir, *jc; + int nbytes; + + if(new_nzmax == old_nzmax) return; + nbytes = new_nzmax * sizeof(*ptr); + ptr = mxGetPr(spArray); + newptr = mxRealloc(ptr, nbytes); + mxSetPr(spArray, newptr); + nbytes = new_nzmax * sizeof(*ir); + ir = mxGetIr(spArray); + newptr = mxRealloc(ir, nbytes); + mxSetIr(spArray, newptr); + jc = mxGetJc(spArray); + jc[0] = 0; + jc[1] = new_nzmax; + mxSetNzmax(spArray, new_nzmax); +} + +mxArray* convert_table_to_sparse(const double *bT, const int *index, const int nzCounts, const int NB){ + mxArray *spTable; + int i, *irs, *jcs; + double *sr; + + spTable = mxCreateSparse(NB, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + sr[i] = bT[i]; + irs[i] = index[i]; + } + return spTable; +} + +mxArray* convert_ill_table_to_sparse(const double *bigTable, const int *sequence, const int nzCounts, const int NB){ + mxArray *spTable; + int i, temp, *irs, *jcs, count=0; + double *sr; + + spTable = mxCreateSparse(NB, 1, nzCounts, mxREAL); + sr = mxGetPr(spTable); + irs = mxGetIr(spTable); + jcs = mxGetJc(spTable); + + jcs[0] = 0; + jcs[1] = nzCounts; + + for(i=0; i<nzCounts; i++){ + irs[i] = sequence[count]; + count++; + temp = sequence[count]; + sr[i] = bigTable[temp]; + count++; + } + return spTable; +} + +void multiply_null_by_fuPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, NB, NS, siz_b, siz_s, ndim, nzCounts=0; + int *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2, *bir, *bjc; + double *pbDomain, *psDomain, *pbSize, *psSize, *spr, *bpr, value; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + siz_b = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + siz_s = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<siz_b; i++){ + NB *= (int)pbSize[i]; + } + NS = 1; + for(i=0; i<siz_s; i++){ + NS *= (int)psSize[i]; + } + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + + pTemp1 = mxCreateSparse(NB, 1, NB, mxREAL); + bpr = mxGetPr(pTemp1); + bir = mxGetIr(pTemp1); + bjc = mxGetJc(pTemp1); + bjc[0] = 0; + bjc[1] = NB; + + if(NS == 1){ + value = *spr; + for(i=0; i<NB; i++){ + bpr[i] = value; + bir[i] = i; + } + nzCounts = NB; + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + reset_nzmax(pTemp1, NB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp1); + return; + } + + if(NS == NB){ + for(i=0; i<NB; i++){ + if(spr[i] != 0){ + bpr[nzCounts] = spr[i]; + bir[nzCounts] = i; + nzCounts++; + } + } + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + reset_nzmax(pTemp1, NB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp1); + return; + } + + mask = malloc(siz_s * sizeof(int)); + count = 0; + for(i=0; i<siz_s; i++){ + for(j=0; j<siz_b; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + ndim = siz_b; + sx = (int *)malloc(sizeof(int)*ndim); + sy = (int *)malloc(sizeof(int)*ndim); + for(i=0; i<ndim; i++){ + sx[i] = (int)pbSize[i]; + sy[i] = 1; + } + for(i=0; i<count; i++){ + sy[mask[i]] = sx[mask[i]]; + } + + s = (int *)malloc(sizeof(int)*ndim); + *(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1; + subs = (int *)malloc(sizeof(int)*ndim); + cpsy2 = (int *)malloc(sizeof(int)*ndim); + for(i = 0; i < ndim; i++){ + subs[i] = 0; + s[i] = sx[i] - 1; + } + + for(i = 0; i < ndim-1; i++){ + cpsy[i+1] = cpsy[i]*sy[i]--; + cpsy2[i] = cpsy[i]*sy[i]; + } + cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]); + + for(j=0; j<NB; j++){ + if(*spr != 0){ + bpr[nzCounts] = *spr; + bir[nzCounts] = j; + nzCounts++; + } + for(i = 0; i < ndim; i++){ + if(subs[i] == s[i]){ + subs[i] = 0; + if(sy[i]) + spr -= cpsy2[i]; + } + else{ + subs[i]++; + if(sy[i]) + spr += cpsy[i]; + break; + } + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + reset_nzmax(pTemp1, NB, nzCounts); + mxSetField(bigPot, 0, "T", pTemp1); + + free(sx); + free(sy); + free(s); + free(cpsy); + free(subs); + free(cpsy2); + free(mask); +} + +void multiply_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex, nzCounts=0; + int *samemask, *diffmask, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *sequence, *weight; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *spr; + mxArray *pTemp, *pTemp1; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + NS = 1; + for(i=0; i<sdim; i++){ + NS *= (int)psSize[i]; + } + ND = NB / NS; + + if(ND == 1){ + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp1 = mxGetField(smallPot, 0, "T"); + pTemp = mxDuplicateArray(pTemp1); + mxSetField(bigPot, 0, "T", pTemp); + return; + } + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + NZB = ND * NZS; + + diffdim = bdim - sdim; + sequence = malloc(NZB * 2 * sizeof(int)); + bigTable = malloc(NZB * sizeof(double)); + samemask = malloc(sdim * sizeof(int)); + diffmask = malloc(diffdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + weight = malloc(ND * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + count1 = 0; + for(i=0; i<bdim; i++){ + match = 0; + for(j=0; j<sdim; j++){ + if(pbDomain[i] == psDomain[j]){ + samemask[count] = i; + match = 1; + count++; + break; + } + } + if(match == 0){ + diffmask[count1] = i; + count1++; + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + count = 0; + compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim); + for(i=0; i<NZS; i++){ + sindex = sir[i]; + ind_subv(sindex, sCumprod, sdim, ssubv); + temp = 0; + for(j=0; j<sdim; j++){ + temp += ssubv[j] * bCumprod[samemask[j]]; + } + for(j=0; j<ND; j++){ + bindex = weight[j] + temp; + bigTable[nzCounts] = spr[i]; + sequence[count] = bindex; + count++; + sequence[count] = nzCounts; + nzCounts++; + count++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + qsort(sequence, nzCounts, sizeof(int) * 2, compare); + pTemp = convert_ill_table_to_sparse(bigTable, sequence, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(sequence); + free(bigTable); + free(samemask); + free(diffmask); + free(bCumprod); + free(sCumprod); + free(weight); + free(ssubv); +} + +void multiply_spPot_by_fuPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, bindex, sindex, nzCounts=0; + int *mask, *index, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value; + mxArray *pTemp; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + + bigTable = malloc(NZB * sizeof(double)); + index = malloc(NZB * sizeof(double)); + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + value = spr[sindex]; + if(value != 0){ + bigTable[nzCounts] = bpr[i] * value; + index[nzCounts] = bindex; + nzCounts++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(bigTable); + free(index); + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + +void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){ + int i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0; + int *mask, *index, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv; + double *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value; + mxArray *pTemp; + + pTemp = mxGetField(bigPot, 0, "domain"); + pbDomain = mxGetPr(pTemp); + bdim = mxGetNumberOfElements(pTemp); + pTemp = mxGetField(smallPot, 0, "domain"); + psDomain = mxGetPr(pTemp); + sdim = mxGetNumberOfElements(pTemp); + + pTemp = mxGetField(bigPot, 0, "sizes"); + pbSize = mxGetPr(pTemp); + pTemp = mxGetField(smallPot, 0, "sizes"); + psSize = mxGetPr(pTemp); + + NB = 1; + for(i=0; i<bdim; i++){ + NB *= (int)pbSize[i]; + } + + pTemp = mxGetField(bigPot, 0, "T"); + bpr = mxGetPr(pTemp); + bir = mxGetIr(pTemp); + bjc = mxGetJc(pTemp); + NZB = bjc[1]; + + pTemp = mxGetField(smallPot, 0, "T"); + spr = mxGetPr(pTemp); + sir = mxGetIr(pTemp); + sjc = mxGetJc(pTemp); + NZS = sjc[1]; + + bigTable = malloc(NZB * sizeof(double)); + index = malloc(NZB * sizeof(double)); + mask = malloc(sdim * sizeof(int)); + bCumprod = malloc(bdim * sizeof(int)); + sCumprod = malloc(sdim * sizeof(int)); + bsubv = malloc(bdim * sizeof(int)); + ssubv = malloc(sdim * sizeof(int)); + + for(i=0; i<NZB; i++){ + bigTable[i] = 0; + } + count = 0; + for(i=0; i<sdim; i++){ + for(j=0; j<bdim; j++){ + if(psDomain[i] == pbDomain[j]){ + mask[count] = j; + count++; + break; + } + } + } + + bCumprod[0] = 1; + for(i=0; i<bdim-1; i++){ + bCumprod[i+1] = bCumprod[i] * (int)pbSize[i]; + } + sCumprod[0] = 1; + for(i=0; i<sdim-1; i++){ + sCumprod[i+1] = sCumprod[i] * (int)psSize[i]; + } + + for(i=0; i<NZB; i++){ + value = bpr[i]; + bindex = bir[i]; + ind_subv(bindex, bCumprod, bdim, bsubv); + for(j=0; j<sdim; j++){ + ssubv[j] = bsubv[mask[j]]; + } + sindex = subv_ind(sdim, sCumprod, ssubv); + result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare); + if(result){ + position = result - sir; + value *= spr[position]; + bigTable[nzCounts] = value; + index[nzCounts] = bindex; + nzCounts++; + } + } + + pTemp = mxGetField(bigPot, 0, "T"); + if(pTemp)mxDestroyArray(pTemp); + pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB); + mxSetField(bigPot, 0, "T", pTemp); + + free(bigTable); + free(index); + free(mask); + free(bCumprod); + free(sCumprod); + free(bsubv); + free(ssubv); +} + + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){ + int i, j, c, loop, nNodes, nCliques, ndomain, dims[2]; + double *pClqs, *pr, *pt, *pSize; + mxArray *pTemp, *pTemp1, *pStruct, *pCliques, *pBigpot, *pSmallpot; + const char *field_names[] = {"domain", "T", "sizes"}; + + nNodes = mxGetNumberOfElements(prhs[1]); + pCliques = mxGetField(prhs[0], 0, "cliques"); + nCliques = mxGetNumberOfElements(pCliques); + pTemp = mxGetField(prhs[0], 0, "eff_node_sizes"); + pSize = mxGetPr(pTemp); + + plhs[0] = mxCreateCellArray(1, &nCliques); + for(i=0; i<nCliques; i++){ + pStruct = mxCreateStructMatrix(1, 1, 3, field_names); + mxSetCell(plhs[0], i, pStruct); + pTemp = mxGetCell(pCliques, i); + ndomain = mxGetNumberOfElements(pTemp); + pt = mxGetPr(pTemp); + pTemp1 = mxDuplicateArray(pTemp); + mxSetField(pStruct, 0, "domain", pTemp1); + + pTemp = mxCreateDoubleMatrix(1, ndomain, mxREAL); + mxSetField(pStruct, 0, "sizes", pTemp); + pr = mxGetPr(pTemp); + for(j=0; j<ndomain; j++){ + pr[j] = pSize[(int)pt[j]-1]; + } + } + + pClqs = mxGetPr(prhs[1]); + for(loop=0; loop<nNodes; loop++){ + c = (int)pClqs[loop] - 1; + pSmallpot = mxGetCell(prhs[2], loop); + pTemp = mxGetField(pSmallpot, 0, "T"); + pBigpot = mxGetCell(plhs[0], c); + pTemp1 = mxGetField(pBigpot, 0, "T"); + if(pTemp1){ + if(mxIsSparse(pTemp)) + multiply_spPot_by_spPot(pBigpot, pSmallpot); + else multiply_spPot_by_fuPot(pBigpot, pSmallpot); + } + else{ + if(mxIsSparse(pTemp)) + multiply_null_by_spPot(pBigpot, pSmallpot); + else multiply_null_by_fuPot(pBigpot, pSmallpot); + } + } + + dims[0] = nCliques; + dims[1] = nCliques; + plhs[1] = mxCreateCellArray(2, dims); +} + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot1.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot1.m new file mode 100644 index 00000000..857e6266 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot1.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_sparse_inf_engine/set_fields.m b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_inf_engine/set_fields.m new file mode 100644 index 00000000..e75cfa45 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@jtree_sparse_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 diff --git a/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Entries new file mode 100644 index 00000000..c9482cbd --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Entries @@ -0,0 +1,4 @@ +/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/likelihood_weighting_inf_engine.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/static/@likelihood_weighting_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Repository new file mode 100644 index 00000000..e39429d7 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/enter_evidence.m new file mode 100644 index 00000000..62e252aa --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/enter_evidence.m @@ -0,0 +1,39 @@ +function [engine, ll] = enter_evidence(engine, evidence, nsamples) +% ENTER_EVIDENCE Add the specified evidence to the network (likelihood_weighting) +% [engine, ll] = enter_evidence(engine, evidence, nsamples) +% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector) +% +% If nsamples is not specified, the value specified when the engine was created will be used. +% ll (log-likelihood) is set to []. + +ll = []; +if nargin < 3, nsamples = engine.nsamples; end + +bnet = bnet_from_engine(engine); +N = length(bnet.dag); +samples = cell(nsamples, N); +weights = zeros(1, nsamples); + +ns = bnet.node_sizes; +original_evidence = evidence; +observed = ~isemptycell(original_evidence); +for s=1:nsamples + evidence = original_evidence(:); % must be a column vector + w = 1; + for i=1:N + ps = parents(bnet.dag, i); + e = bnet.equiv_class(i); + if observed(i) + p = exp(log_prob_node(bnet.CPD{e}, evidence(i), evidence(ps))); + w = w * p; + else + x = sample_node(bnet.CPD{e}, evidence(ps)); + evidence{i} = x; + end + end + samples(s,:) = evidence; + weights(s) = w; +end + +engine.samples = samples; +engine.weights = weights; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/likelihood_weighting_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/likelihood_weighting_inf_engine.m new file mode 100644 index 00000000..eb1794fa --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/likelihood_weighting_inf_engine.m @@ -0,0 +1,25 @@ +function engine = likelihood_weighting_inf_engine(bnet, varargin) +% LIKELIHOOD_WEIGHTING_INF_ENGINE +% engine = likelihood_weighting_inf_engine(bnet, ...) +% +% Optional arguments [defaults] +% nsamples - [500] + +nsamples = 500; + +if nargin >= 2 + args = varargin; + nargs = length(args); + for i=1:2:nargs + switch args{i}, + case 'nsamples', nsamples= args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + +engine.nsamples = nsamples; +engine.samples = []; +engine.weights = []; +engine = class(engine, 'likelihood_weighting_inf_engine', inf_engine(bnet)); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..d00ee606 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@likelihood_weighting_inf_engine/marginal_nodes.m @@ -0,0 +1,53 @@ +function marginal = marginal_nodes(engine, nodes) +% MARGINAL_NODES Compute the marginal on the specified query nodes (likelihood_weighting) +% marginal = marginal_nodes(engine, nodes) + +bnet = bnet_from_engine(engine); +ddom = myintersect(nodes, bnet.dnodes); +cdom = myintersect(nodes, bnet.cnodes); +nsamples = size(engine.samples, 1); +ns = bnet.node_sizes; + +%w = normalise(engine.weights); +w = engine.weights; +if mysubset(nodes, ddom) + T = 0*myones(ns(nodes)); + P = prod(ns(nodes)); + indices = ind2subv(ns(nodes), 1:P); + samples = reshape(cat(1, engine.samples{:,nodes}), nsamples, length(nodes)); + for j = 1:P + rows = find_rows(samples, indices(j,:)); + T(j) = sum(w(rows)); + end + T = normalise(T); + marginal.T = T; +elseif subset(nodes, cdom) + samples = reshape(cat(1, engine.samples{:,nodes}), nsamples*sum(ns(nodes)), length(nodes)); + [marginal.mu, marginal.Sigma] = wstats(samples', normalise(w)); +else + error('can''t handle mixed marginals yet'); +end + +marginal.domain = nodes; + +%%%%%%%%% + +function rows = find_rows(M, v) +% FINDROWS Find rows which are equal to a specified vector +% rows = findrows(M, v) +% Each row of M is a sample + +temp = abs(M - repmat(v, size(M, 1), 1)); +rows = find(sum(temp,2) == 0); + +%%%%%%%% + +function [mu, Sigma] = wstats(X, w) + +% Computes the weighted mean and weighted covariance matrix for a given +% set of observations X(:,i), and a set of normalised weights w(i). +% Each column of X is a sample. + +d = X - repmat(X * w', 1, size(X, 2)); +mu = sum(X .* repmat(w, size(X, 1), 1), 2); +Sigma = d * diag(w) * d'; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Entries new file mode 100644 index 00000000..50ed260c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Entries @@ -0,0 +1,7 @@ +/bethe_free_energy.m/1.1.1.1/Sun Jul 6 20:57:18 2003// +/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002// +/loopy_converged.m/1.1.1.1/Wed May 29 15:59:56 2002// +/marginal_family.m/1.1.1.1/Fri Oct 18 20:05:16 2002// +/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002// +/pearl_inf_engine.m/1.1.1.1/Sat Jan 11 18:53:28 2003// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Entries.Log b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Entries.Log new file mode 100644 index 00000000..b2cd71e0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Entries.Log @@ -0,0 +1 @@ +A D/private//// diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Repository new file mode 100644 index 00000000..d88c6406 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@pearl_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/bethe_free_energy.m b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/bethe_free_energy.m new file mode 100644 index 00000000..67495fd0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/bethe_free_energy.m @@ -0,0 +1,50 @@ +function loglik = bethe_free_energy(engine, evidence) +% BETHE_FREE_ENERGY Compute Bethe free energy approximation to the log likelihood +% loglik = bethe_free_energy(engine, evidence) +% +% The Bethe free energy is given by an exact energy term and an approximate entropy term. +% Energy +% E = -sum_f sum_i b(f,i) ln theta(f,i) +% where b(f,i) = approximate Pr(family f = i) +% and theta(f,i) = Pr(f = i) +% Entropy +% S = H1 - H2 +% H1 = sum_f sum_p H(b(f)) +% where b(f) = belief on family f, H(.) = entropy +% H2 = sum_n (q(n)-1) H(b(n)) +% where q(n) = num. neighbors of n +% +% This function was written by Yair Weiss, 8/22/01. + +hidden = find(isemptycell(evidence)); +bnet = bnet_from_engine(engine); +N = length(bnet.dag); + +add_ev = 1; +E=0;H1=0;H2=0; +loglik=0; +for n=1:N + ps=parents(bnet.dag,n); + if (length(ps)==0) % root node + qi=length(children(bnet.dag,n))-1; + else + qi=length(children(bnet.dag,n)); + end + bf = marginal_family(engine, n, add_ev); + bf = bf.T(:); + e = bnet.equiv_class(n); + T = CPD_to_CPT(bnet.CPD{e}); + T = T(:); + E = E-sum(log(T+(T==0)).*bf); + + if length(ps) > 0 + % root nodes don't count as fmailies + H1 = H1+sum(log(bf+(bf==0)).*bf); + end + + bi = marginal_nodes(engine, n, add_ev); + bi = bi.T(:); + H2 = H2+qi*sum(log(bi+(bi==0)).*bi); +end +loglik=E+H1-H2; +loglik=-loglik; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/enter_evidence.m new file mode 100644 index 00000000..65e45b15 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/enter_evidence.m @@ -0,0 +1,153 @@ +function [engine, loglik, niter] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Add the specified evidence to the network (pearl) +% [engine, loglik, num_iter] = enter_evidence(engine, evidence, ...) +% evidence{i} = [] if 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 pa irs: +% [default value in brackets] +% +% maximize - if 1, does max-product instead of sum-product [0] +% 'filename' - msgs will be printed to this file, so you can assess convergence while it runs [engine.filename] +% +% e.g., engine = enter_evidence(engine, ev, 'maximize', 1) +% +% For discrete nodes, loglik is the negative Bethe free energy evaluated at the final beliefs. +% For Gaussian nodes, loglik is currently always 0. +% +% 'num_iter' returns the number of iterations used. + +maximize = 0; +filename = engine.filename; + +% parse optional params +args = varargin; +nargs = length(args); +if nargs > 0 + for i=1:2:nargs + switch args{i}, + case 'maximize', maximize = args{i+1}; + case 'filename', filename = args{i+1}; + otherwise, + error(['invalid argument name ' args{i}]); + end + end +end + + +if maximize + error('can''t handle max-prop yet') +end + +engine.maximize = maximize; +engine.filename = filename; +engine.bel = []; % reset if necessary + +bnet = bnet_from_engine(engine); +N = length(bnet.dag); +ns = bnet.node_sizes(:); + +observed_bitv = ~isemptycell(evidence); +disconnected = find(engine.disconnected_nodes_bitv); +if ~all(observed_bitv(disconnected)) + error(['The following discrete nodes must be observed: ' num2str(disconnected)]) +end +msg = init_pearl_msgs(engine.msg_type, engine.msg_dag, ns, evidence); + +niter = 1; +switch engine.protocol + case 'parallel', [msg, niter] = parallel_protocol(engine, evidence, msg); + case 'tree', msg = tree_protocol(engine, evidence, msg); + otherwise, + error(['unrecognized protocol ' engine.protocol]) +end +engine.niter = niter; + +engine.marginal = cell(1,N); +nodes = find(~engine.disconnected_nodes_bitv); +for n=nodes(:)' + engine.marginal{n} = compute_bel(engine.msg_type, msg{n}.pi, msg{n}.lambda); +end + +engine.evidence = evidence; % needed by marginal_nodes and marginal_family +engine.msg = msg; % needed by marginal_family + +if (nargout >= 2) + if (engine.msg_type == 'd') + loglik = bethe_free_energy(engine, evidence); + else + loglik = 0; + end +end + + + +%%%%%%%%%%% + +function msg = init_pearl_msgs(msg_type, dag, ns, evidence) +% INIT_MSGS Initialize the lambda/pi message and state vectors +% msg = init_msgs(dag, ns, evidence) +% + +N = length(dag); +msg = cell(1,N); +observed = ~isemptycell(evidence); +lam_msg = 1; + +for n=1:N + ps = parents(dag, n); + msg{n}.pi_from_parent = cell(1, length(ps)); + for i=1:length(ps) + p = ps(i); + msg{n}.pi_from_parent{i} = mk_msg(msg_type, ns(p)); + end + + cs = children(dag, n); + msg{n}.lambda_from_child = cell(1, length(cs)); + for i=1:length(cs) + c = cs(i); + msg{n}.lambda_from_child{i} = mk_msg(msg_type, ns(n), lam_msg); + end + + msg{n}.lambda = mk_msg(msg_type, ns(n), lam_msg); + msg{n}.pi = mk_msg(msg_type, ns(n)); + + if observed(n) + msg{n}.lambda_from_self = mk_msg_with_evidence(msg_type, ns(n), evidence{n}); + else + msg{n}.lambda_from_self = mk_msg(msg_type, ns(n), lam_msg); + end +end + + + +%%%%%%%%% + +function msg = mk_msg(msg_type, sz, is_lambda_msg) + +if nargin < 3, is_lambda_msg = 0; end + +switch msg_type + case 'd', msg = ones(sz, 1); + case 'g', + if is_lambda_msg + msg.precision = zeros(sz, sz); + msg.info_state = zeros(sz, 1); + else + msg.Sigma = zeros(sz, sz); + msg.mu = zeros(sz,1); + end +end + +%%%%%%%%%%%% + +function msg = mk_msg_with_evidence(msg_type, sz, val) + +switch msg_type + case 'd', + msg = zeros(sz, 1); + msg(val) = 1; + case 'g', + %msg.observed_val = val(:); + msg.precision = inf; + msg.mu = val(:); +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/loopy_converged.m b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/loopy_converged.m new file mode 100644 index 00000000..fba4f2fd --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/loopy_converged.m @@ -0,0 +1,13 @@ +function niter = loopy_converged(engine) +% LOOPY_CONVERGED Did loopy belief propagation converge? 0 means no, eles we return the num. iterations. +% function niter = loopy_converged(engine) +% +% We use a simple heuristic: we say convergence occurred if the number of iterations +% used was less than the maximum allowed. + +if engine.niter == engine.max_iter + niter = 0; +else + niter = engine.niter; +end +%conv = (strcmp(engine.protocol, 'tree') | (engine.niter < engine.max_iter)); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/marginal_family.m b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/marginal_family.m new file mode 100644 index 00000000..9226afda --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/marginal_family.m @@ -0,0 +1,80 @@ +function m = marginal_family(engine, n, add_ev) +% MARGINAL_FAMILY Compute the marginal on i's family (loopy) +% m = marginal_family(engine, n, add_ev) + +if nargin < 3, add_ev = 0; end + +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes; +ps = parents(bnet.dag, n); +dom = [ps n]; +CPD = bnet.CPD{bnet.equiv_class(n)}; + +switch engine.msg_type + case 'd', + % The method is similar to the following HMM equation: + % xi(i,j,t) = normalise( alpha(i,t) * transmat(i,j) * obsmat(j,t+1) * beta(j,t+1) ) + % where xi(i,j,t) = Pr(Q(t)=i, Q(t+1)=j | y(1:T)) + % beta == lambda, alpha == pi, alpha from each parent = pi msg + % In general, if A,B are parents of C, + % P(A,B,C) = P(C|A,B) pi_msg(A->C) pi_msg(B->C) lambda(C) + % where lambda(C) = P(ev below and including C|C) = prod incoming lamba_msg(children->C) + % and pi_msg(X->C) = P(X|ev above) etc + + T = dpot(dom, ns(dom), CPD_to_CPT(CPD)); + for j=1:length(ps) + p = ps(j); + pi_msg = dpot(p, ns(p), engine.msg{n}.pi_from_parent{j}); + T = multiply_by_pot(T, pi_msg); + end + lambda = dpot(n, ns(n), engine.msg{n}.lambda); + T = multiply_by_pot(T, lambda); + T = normalize_pot(T); + m = pot_to_marginal(T); + if ~add_ev + m.T = shrink_obs_dims_in_table(m.T, dom, engine.evidence); + end + case 'g', + if engine.disconnected_nodes_bitv(n) + m.T = 1; + m.domain = dom; + if add_ev + m = add_ev_to_dmarginal(m, engine.evidence, ns) + end + return; + end + + [m, C, W] = gaussian_CPD_params_given_dps(CPD, dom, engine.evidence); + cdom = myintersect(dom, bnet.cnodes); + pot = linear_gaussian_to_cpot(m, C, W, dom, ns, cdom, engine.evidence); + % linear_gaussian_to_cpot will set the effective size of observed nodes to 0, + % so we need to do this explicitely for the messages, too, + % so they are all the same size. + obs_bitv = ~isemptycell(engine.evidence); + ps = parents(engine.msg_dag, n); + for j=1:length(ps) + p = ps(j); + msg = engine.msg{n}.pi_from_parent{j}; + if obs_bitv(p) + pi_msg = mpot(p, 0); + else + pi_msg = mpot(p, ns(p), 0, msg.mu, msg.Sigma); + end + pot = multiply_by_pot(pot, mpot_to_cpot(pi_msg)); + end + msg = engine.msg{n}.lambda; + if obs_bitv(n) + lambda = cpot(n, 0); + else + lambda = cpot(n, ns(n), 0, msg.info_state, msg.precision); + end + pot = multiply_by_pot(pot, lambda); + m = pot_to_marginal(pot); + if add_ev + m = add_evidence_to_gmarginal(m, engine.evidence, bnet.node_sizes, bnet.cnodes); + end +end + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..bee6ec37 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/marginal_nodes.m @@ -0,0 +1,43 @@ +function marginal = marginal_nodes(engine, query, add_ev) +% MARGINAL_NODES Compute the marginal on the specified query nodes (loopy) +% marginal = marginal_nodes(engine, query, add_ev) +% +% 'query' must be a single node. +% add_ev is an optional argument; if 1, observed nodes will be set to their original size, +% otherwise they will be treated like points. + +if nargin < 3, add_ev = 0; end + +if length(query) > 1 + error('can only compute marginal on single nodes or families') +end +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes(:); + +switch engine.msg_type + case 'd', + T = engine.marginal{query}; + if ~add_ev + marginal.T = shrink_obs_dims_in_table(T, query, engine.evidence); + else + marginal.T = T; + end + marginal.domain = query; + + case 'g', + if engine.disconnected_nodes_bitv(query) + marginal.T = 1; + marginal.domain = query; + if add_ev + marginal = add_ev_to_dmarginal(marginal, engine.evidence, ns) + end + return; + end + + marginal = engine.marginal{query}; + marginal.domain = query; + if ~add_ev + marginal = shrink_obs_dims_in_gaussian(marginal, query, engine.evidence, ns); + end +end + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/pearl_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/pearl_inf_engine.m new file mode 100644 index 00000000..d4eb3059 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/pearl_inf_engine.m @@ -0,0 +1,158 @@ +function engine = pearl_inf_engine(bnet, varargin) +% PEARL_INF_ENGINE Pearl's algorithm (belief propagation) +% engine = pearl_inf_engine(bnet, ...) +% +% If the graph has no loops (undirected cycles), you should use the tree protocol, +% and the results will be exact. +% Otherwise, you should use the parallel protocol, and the results may be approximate. +% +% Optional arguments [default in brackets] +% 'protocol' - tree or parallel ['parallel'] +% +% Optional arguments for the loopy case +% 'max_iter' - specifies the max num. iterations to perform [2*num nodes] +% 'tol' - convergence criterion on messages [1e-3] +% 'momentum' - msg = (m*old + (1-m)*new). [m=0] +% 'filename' - msgs will be printed to this file, so you can assess convergence while it runs [[]] +% 'storebel' - 1 means save engine.bel{n,t} for every iteration t and hidden node n [0] +% +% If there are discrete and cts nodes, we assume all the discretes are observed. In this +% case, you must use the parallel protocol, and the evidence pattern must be fixed. + + +N = length(bnet.dag); +protocol = 'parallel'; +max_iter = 2*N; +% We use N+2 for the following reason: +% In N iterations, we get the exact answer for a tree. +% In the N+1st iteration, we notice that the results are the same as before, and terminate. +% In loopy_converged, we see that N+1 < max = N+2, and declare convergence. +tol = 1e-3; +momentum = 0; +filename = []; +storebel = 0; + +args = varargin; +for i=1:2:length(args) + switch args{i}, + case 'protocol', protocol = args{i+1}; + case 'max_iter', max_iter = args{i+1}; + case 'tol', tol = args{i+1}; + case 'momentum', momentum = args{i+1}; + case 'filename', filename = args{i+1}; + case 'storebel', storebel = args{i+1}; + end +end + +engine.filename = filename; +engine.storebel = storebel; +engine.bel = []; + +if strcmp(protocol, 'tree') + % We first send messages up to the root (pivot node), and then back towards the leaves. + % If the bnet is a singly connected graph (no loops), choosing a root induces a directed tree. + % Peot and Shachter discuss ways to pick the root so as to minimize the work, + % taking into account which nodes have changed. + % For simplicity, we always pick the root to be the last node in the graph. + % This means the first pass is equivalent to going forward in time in a DBN. + + engine.root = N; + [engine.adj_mat, engine.preorder, engine.postorder, loopy] = ... + mk_rooted_tree(bnet.dag, engine.root); + % engine.adj_mat might have different edge orientations from bnet.dag + if loopy + error('can only apply tree protocol to loop-less graphs') + end +else + engine.root = []; + engine.adj_mat = []; + engine.preorder = []; + engine.postorder = []; +end + +engine.niter = []; +engine.protocol = protocol; +engine.max_iter = max_iter; +engine.tol = tol; +engine.momentum = momentum; +engine.maximize = []; + +%onodes = find(~isemptycell(evidence)); +onodes = bnet.observed; +engine.msg_type = determine_pot_type(bnet, onodes, 1:N); % needed also by marginal_nodes +if strcmp(engine.msg_type, 'cg') + error('messages must be discrete or Gaussian') +end +[engine.msg_dag, disconnected_nodes] = mk_msg_dag(bnet, engine.msg_type, onodes); +engine.disconnected_nodes_bitv = zeros(1,N); +engine.disconnected_nodes_bitv(disconnected_nodes) = 1; + + +% this is where we store stuff between enter_evidence and marginal_nodes +engine.marginal = cell(1,N); +engine.evidence = []; +engine.msg = []; + +[engine.parent_index, engine.child_index] = mk_loopy_msg_indices(engine.msg_dag); + +engine = class(engine, 'pearl_inf_engine', inf_engine(bnet)); + + +%%%%%%%%% + +function [dag, disconnected_nodes] = mk_msg_dag(bnet, msg_type, onodes) + +% If we are using Gaussian msgs, all discrete nodes must be observed; +% they are then disconnected from the graph, so we don't try to send +% msgs to/from them: their observed value simply serves to index into +% the right set of parameters for the Gaussian nodes (which use CPD.ps +% instead of parents(dag), and hence are unaffected by this "surgery"). + +disconnected_nodes = []; +switch msg_type + case 'd', dag = bnet.dag; + case 'g', + disconnected_nodes = bnet.dnodes; + dag = bnet.dag; + for i=disconnected_nodes(:)' + ps = parents(bnet.dag, i); + cs = children(bnet.dag, i); + if ~isempty(ps), dag(ps, i) = 0; end + if ~isempty(cs), dag(i, cs) = 0; end + end +end + + +%%%%%%%%%% +function [parent_index, child_index] = mk_loopy_msg_indices(dag) +% MK_LOOPY_MSG_INDICES Compute "port numbers" for message passing +% [parent_index, child_index] = mk_loopy_msg_indices(bnet) +% +% child_index{n}(c) = i means c is n's i'th child, i.e., i = find_equiv_posns(c, children(n)) +% child_index{n}(c) = 0 means c is not a child of n. +% parent_index{n}{p} is defined similarly. +% We need to use these indices since the pi_from_parent/ lambda_from_child cell arrays +% cannot be sparse, and hence cannot be indexed by the actual number of the node. +% Instead, we use the number of the "port" on which the message arrived. + +N = length(dag); +child_index = cell(1,N); +parent_index = cell(1,N); +for n=1:N + cs = children(dag, n); + child_index{n} = sparse(1,N); + for i=1:length(cs) + c = cs(i); + child_index{n}(c) = i; + end + ps = parents(dag, n); + parent_index{n} = sparse(1,N); + for i=1:length(ps) + p = ps(i); + parent_index{n}(p) = i; + end +end + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/pearl_inf_engine.m~ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/pearl_inf_engine.m~ new file mode 100644 index 00000000..946233d0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/pearl_inf_engine.m~ @@ -0,0 +1,158 @@ +function engine = pearl_inf_engine(bnet, varargin) +% PEARL_INF_ENGINE Pearl's algorithm (belief propagation) +% engine = pearl_inf_engine(bnet, ...) +% +% If the graph has no loops (undirected cycles), you should use the tree protocol, +% and the results will be exact. +% Otherwise, you should use the parallel protocol, and the results may be approximate. +% +% Optional arguments [default in brackets] +% 'protocol' - tree or parallel ['parallel'] +% +% Optional arguments for the loopy case +% 'max_iter' - specifies the max num. iterations to perform [2*num nodes] +% 'tol' - convergence criterion on messages [1e-3] +% 'momentum' - msg = (m*old + (1-m)*new). [m=0] +% 'filename' - msgs will be printed to this file, so you can assess convergence while it runs [[]] +% 'storebel' - 1 means save engine.bel{n,t} for every iteration t and hidden node n [0] +% +% If there are discrete and cts nodes, we assume all the discretes are observed. In this +% case, you must use the parallel protocol, and the evidence pattern must be fixed. + + +N = length(bnet.dag); +protocol = []; +max_iter = 2*N; +% We use N+2 for the following reason: +% In N iterations, we get the exact answer for a tree. +% In the N+1st iteration, we notice that the results are the same as before, and terminate. +% In loopy_converged, we see that N+1 < max = N+2, and declare convergence. +tol = 1e-3; +momentum = 0; +filename = []; +storebel = 0; + +args = varargin; +for i=1:2:length(args) + switch args{i}, + case 'protocol', protocol = args{i+1}; + case 'max_iter', max_iter = args{i+1}; + case 'tol', tol = args{i+1}; + case 'momentum', momentum = args{i+1}; + case 'filename', filename = args{i+1}; + case 'storebel', storebel = args{i+1}; + end +end + +engine.filename = filename; +engine.storebel = storebel; +engine.bel = []; + +if strcmp(protocol, 'tree') + % We first send messages up to the root (pivot node), and then back towards the leaves. + % If the bnet is a singly connected graph (no loops), choosing a root induces a directed tree. + % Peot and Shachter discuss ways to pick the root so as to minimize the work, + % taking into account which nodes have changed. + % For simplicity, we always pick the root to be the last node in the graph. + % This means the first pass is equivalent to going forward in time in a DBN. + + engine.root = N; + [engine.adj_mat, engine.preorder, engine.postorder, loopy] = ... + mk_rooted_tree(bnet.dag, engine.root); + % engine.adj_mat might have different edge orientations from bnet.dag + if loopy + error('can only apply tree protocol to loop-less graphs') + end +else + engine.root = []; + engine.adj_mat = []; + engine.preorder = []; + engine.postorder = []; +end + +engine.niter = []; +engine.protocol = protocol; +engine.max_iter = max_iter; +engine.tol = tol; +engine.momentum = momentum; +engine.maximize = []; + +%onodes = find(~isemptycell(evidence)); +onodes = bnet.observed; +engine.msg_type = determine_pot_type(bnet, onodes, 1:N); % needed also by marginal_nodes +if strcmp(engine.msg_type, 'cg') + error('messages must be discrete or Gaussian') +end +[engine.msg_dag, disconnected_nodes] = mk_msg_dag(bnet, engine.msg_type, onodes); +engine.disconnected_nodes_bitv = zeros(1,N); +engine.disconnected_nodes_bitv(disconnected_nodes) = 1; + + +% this is where we store stuff between enter_evidence and marginal_nodes +engine.marginal = cell(1,N); +engine.evidence = []; +engine.msg = []; + +[engine.parent_index, engine.child_index] = mk_loopy_msg_indices(engine.msg_dag); + +engine = class(engine, 'pearl_inf_engine', inf_engine(bnet)); + + +%%%%%%%%% + +function [dag, disconnected_nodes] = mk_msg_dag(bnet, msg_type, onodes) + +% If we are using Gaussian msgs, all discrete nodes must be observed; +% they are then disconnected from the graph, so we don't try to send +% msgs to/from them: their observed value simply serves to index into +% the right set of parameters for the Gaussian nodes (which use CPD.ps +% instead of parents(dag), and hence are unaffected by this "surgery"). + +disconnected_nodes = []; +switch msg_type + case 'd', dag = bnet.dag; + case 'g', + disconnected_nodes = bnet.dnodes; + dag = bnet.dag; + for i=disconnected_nodes(:)' + ps = parents(bnet.dag, i); + cs = children(bnet.dag, i); + if ~isempty(ps), dag(ps, i) = 0; end + if ~isempty(cs), dag(i, cs) = 0; end + end +end + + +%%%%%%%%%% +function [parent_index, child_index] = mk_loopy_msg_indices(dag) +% MK_LOOPY_MSG_INDICES Compute "port numbers" for message passing +% [parent_index, child_index] = mk_loopy_msg_indices(bnet) +% +% child_index{n}(c) = i means c is n's i'th child, i.e., i = find_equiv_posns(c, children(n)) +% child_index{n}(c) = 0 means c is not a child of n. +% parent_index{n}{p} is defined similarly. +% We need to use these indices since the pi_from_parent/ lambda_from_child cell arrays +% cannot be sparse, and hence cannot be indexed by the actual number of the node. +% Instead, we use the number of the "port" on which the message arrived. + +N = length(dag); +child_index = cell(1,N); +parent_index = cell(1,N); +for n=1:N + cs = children(dag, n); + child_index{n} = sparse(1,N); + for i=1:length(cs) + c = cs(i); + child_index{n}(c) = i; + end + ps = parents(dag, n); + parent_index{n} = sparse(1,N); + for i=1:length(ps) + p = ps(i); + parent_index{n}(p) = i; + end +end + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/CVS/Entries new file mode 100644 index 00000000..283482a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/CVS/Entries @@ -0,0 +1,5 @@ +/compute_bel.m/1.1.1.1/Wed May 29 15:59:56 2002// +/parallel_protocol.m/1.1.1.1/Sun Aug 21 20:00:12 2005// +/prod_lambda_msgs.m/1.1.1.1/Wed May 29 15:59:56 2002// +/tree_protocol.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/CVS/Repository new file mode 100644 index 00000000..e913d5b6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@pearl_inf_engine/private diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/compute_bel.m b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/compute_bel.m new file mode 100644 index 00000000..ebcbc747 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/compute_bel.m @@ -0,0 +1,24 @@ +function bel = compute_bel(msg_type, pi, lambda) + +switch msg_type, + case 'd', bel = normalise(pi .* lambda); + case 'g', + if isinf(lambda.precision) % ignore pi because lambda is completely certain (observed) + bel.mu = lambda.mu; + bel.Sigma = zeros(length(bel.mu)); % infinite precision => 0 variance + elseif all(pi.Sigma==0) % ignore lambda because pi is completely certain (delta fn prior) + bel.Sigma = pi.Sigma; + bel.mu = pi.mu; + elseif all(isinf(pi.Sigma)) % ignore pi because pi is completely uncertain + bel.Sigma = inv(lambda.precision); + bel.mu = bel.Sigma * lambda.info_state; + elseif all(lambda.precision == 0) % ignore lambda because lambda is completely uncertain + bel.Sigma = pi.Sigma; + bel.mu = pi.mu; + else % combine both pi and lambda + pi_precision = inv(pi.Sigma); + bel.Sigma = inv(pi_precision + lambda.precision); + bel.mu = bel.Sigma*(pi_precision * pi.mu + lambda.info_state); + end + otherwise, error(['unrecognized msg type ' msg_type]) +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/parallel_protocol.m b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/parallel_protocol.m new file mode 100644 index 00000000..8aa178b4 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/parallel_protocol.m @@ -0,0 +1,114 @@ +function [msg, niter] = parallel_protocol(engine, evidence, msg) + +bnet = bnet_from_engine(engine); +N = length(bnet.dag); +ns = bnet.node_sizes(:); + +if ~isempty(engine.filename) + fid = fopen(engine.filename, 'w'); + if fid == 0 + error(['could not open ' engine.filename ' for writing']) + end +else + fid = []; +end + +converged = 0; +iter = 1; +hidden = find(isemptycell(evidence)); +bel = cell(1,N); +old_bel = cell(1,N); +%nodes = mysetdiff(1:N, engine.disconnected_nodes); +nodes = find(~engine.disconnected_nodes_bitv); +while ~converged && (iter <= engine.max_iter) + % Everybody updates their state in parallel + for n=nodes(:)' + cs_msg = children(engine.msg_dag, n); + %msg{n}.lambda = compute_lambda(n, cs, msg); + msg{n}.lambda = prod_lambda_msgs(n, cs_msg, msg, engine.msg_type); + ps_orig = parents(bnet.dag, n); + msg{n}.pi = CPD_to_pi(bnet.CPD{bnet.equiv_class(n)}, engine.msg_type, n, ps_orig, msg, evidence); + end + + changed = 0; + if ~isempty(fid) + fprintf(fid, 'ITERATION %d\n', iter); + end + for n=hidden(:)' % this will not contain any disconnected nodes + old_bel{n} = bel{n}; + bel{n} = compute_bel(engine.msg_type, msg{n}.pi, msg{n}.lambda); + if ~isempty(fid) + fprintf(fid, 'node %d: %s\n', n, bel_to_str(bel{n}, engine.msg_type)); + end + if engine.storebel + engine.bel{n,iter} = bel{n}; + end + if (iter == 1) | ~approxeq_bel(bel{n}, old_bel{n}, engine.tol, engine.msg_type) + changed = 1; + end + end + %converged = ~changed; + converged = ~changed && (iter > 1); % Sonia Leach changed this + + if ~converged + % Everybody sends to all their neighbors in parallel + for n=nodes(:)' + % lambda msgs to parents + ps_msg = parents(engine.msg_dag, n); + ps_orig = parents(bnet.dag, n); + for p=ps_msg(:)' + j = engine.child_index{p}(n); % n is p's j'th child + old_msg = msg{p}.lambda_from_child{j}(:); + new_msg = CPD_to_lambda_msg(bnet.CPD{bnet.equiv_class(n)}, engine.msg_type, n, ps_orig, ... + msg, p, evidence); + lam_msg = convex_combination_msg(old_msg, new_msg, engine.momentum, engine.msg_type); + msg{p}.lambda_from_child{j} = lam_msg; + end + + % pi msgs to children + cs_msg = children(engine.msg_dag, n); + for c=cs_msg(:)' + j = engine.parent_index{c}(n); % n is c's j'th parent + old_msg = msg{c}.pi_from_parent{j}(:); + %new_msg = compute_pi_msg(n, cs, msg, c)); + new_msg = compute_bel(engine.msg_type, msg{n}.pi, prod_lambda_msgs(n, cs_msg, msg, engine.msg_type, c)); + pi_msg = convex_combination_msg(old_msg, new_msg, engine.momentum, engine.msg_type); + msg{c}.pi_from_parent{j} = pi_msg; + end + end + iter = iter + 1; + end +end + +if fid > 0, fclose(fid); end +%niter = iter - 1; +niter = iter; + +%%%%%%%%%% + +function str = bel_to_str(bel, type) + +switch type + case 'd', str = sprintf('%9.4f ', bel(:)'); + case 'g', str = sprintf('%9.4f ', bel.mu(:)'); +end + + +%%%%%%% + +function a = approxeq_bel(bel1, bel2, tol, type) + +switch type + case 'd', a = approxeq(bel1, bel2, tol); + case 'g', a = approxeq(bel1.mu, bel2.mu, tol) && approxeq(bel1.Sigma, bel2.Sigma, tol); +end + + +%%%%%%% + +function msg = convex_combination_msg(old_msg, new_msg, old_weight, type) + +switch type + case 'd', msg = old_weight * old_msg + (1-old_weight)*new_msg; + case 'g', msg = new_msg; +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/parallel_protocol.m~ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/parallel_protocol.m~ new file mode 100644 index 00000000..cc6fe6b3 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/parallel_protocol.m~ @@ -0,0 +1,114 @@ +function [msg, niter] = parallel_protocol(engine, evidence, msg) + +bnet = bnet_from_engine(engine); +N = length(bnet.dag); +ns = bnet.node_sizes(:); + +if ~isempty(engine.filename) + fid = fopen(engine.filename, 'w'); + if fid == 0 + error(['could not open ' engine.filename ' for writing']) + end +else + fid = 0; +end + +converged = 0; +iter = 1; +hidden = find(isemptycell(evidence)); +bel = cell(1,N); +old_bel = cell(1,N); +%nodes = mysetdiff(1:N, engine.disconnected_nodes); +nodes = find(~engine.disconnected_nodes_bitv); +while ~converged & (iter <= engine.max_iter) + % Everybody updates their state in parallel + for n=nodes(:)' + cs_msg = children(engine.msg_dag, n); + %msg{n}.lambda = compute_lambda(n, cs, msg); + msg{n}.lambda = prod_lambda_msgs(n, cs_msg, msg, engine.msg_type); + ps_orig = parents(bnet.dag, n); + msg{n}.pi = CPD_to_pi(bnet.CPD{bnet.equiv_class(n)}, engine.msg_type, n, ps_orig, msg, evidence); + end + + changed = 0; + if ~isempty(fid) + fprintf(fid, 'ITERATION %d\n', iter); + end + for n=hidden(:)' % this will not contain any disconnected nodes + old_bel{n} = bel{n}; + bel{n} = compute_bel(engine.msg_type, msg{n}.pi, msg{n}.lambda); + if ~isempty(fid) + fprintf(fid, 'node %d: %s\n', n, bel_to_str(bel{n}, engine.msg_type)); + end + if engine.storebel + engine.bel{n,iter} = bel{n}; + end + if (iter == 1) | ~approxeq_bel(bel{n}, old_bel{n}, engine.tol, engine.msg_type) + changed = 1; + end + end + %converged = ~changed; + converged = ~changed & (iter > 1); % Sonia Leach changed this + + if ~converged + % Everybody sends to all their neighbors in parallel + for n=nodes(:)' + % lambda msgs to parents + ps_msg = parents(engine.msg_dag, n); + ps_orig = parents(bnet.dag, n); + for p=ps_msg(:)' + j = engine.child_index{p}(n); % n is p's j'th child + old_msg = msg{p}.lambda_from_child{j}(:); + new_msg = CPD_to_lambda_msg(bnet.CPD{bnet.equiv_class(n)}, engine.msg_type, n, ps_orig, ... + msg, p, evidence); + lam_msg = convex_combination_msg(old_msg, new_msg, engine.momentum, engine.msg_type); + msg{p}.lambda_from_child{j} = lam_msg; + end + + % pi msgs to children + cs_msg = children(engine.msg_dag, n); + for c=cs_msg(:)' + j = engine.parent_index{c}(n); % n is c's j'th parent + old_msg = msg{c}.pi_from_parent{j}(:); + %new_msg = compute_pi_msg(n, cs, msg, c)); + new_msg = compute_bel(engine.msg_type, msg{n}.pi, prod_lambda_msgs(n, cs_msg, msg, engine.msg_type, c)); + pi_msg = convex_combination_msg(old_msg, new_msg, engine.momentum, engine.msg_type); + msg{c}.pi_from_parent{j} = pi_msg; + end + end + iter = iter + 1; + end +end + +if fid > 0, fclose(fid); end +%niter = iter - 1; +niter = iter; + +%%%%%%%%%% + +function str = bel_to_str(bel, type) + +switch type + case 'd', str = sprintf('%9.4f ', bel(:)'); + case 'g', str = sprintf('%9.4f ', bel.mu(:)'); +end + + +%%%%%%% + +function a = approxeq_bel(bel1, bel2, tol, type) + +switch type + case 'd', a = approxeq(bel1, bel2, tol); + case 'g', a = approxeq(bel1.mu, bel2.mu, tol) & approxeq(bel1.Sigma, bel2.Sigma, tol); +end + + +%%%%%%% + +function msg = convex_combination_msg(old_msg, new_msg, old_weight, type) + +switch type + case 'd', msg = old_weight * old_msg + (1-old_weight)*new_msg; + case 'g', msg = new_msg; +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/prod_lambda_msgs.m b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/prod_lambda_msgs.m new file mode 100644 index 00000000..5a96d259 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/prod_lambda_msgs.m @@ -0,0 +1,29 @@ +function lam = prod_lambda_msgs(n, cs, msg, msg_type, except) + +if nargin < 5, except = -1; end + +lam = msg{n}.lambda_from_self; +switch msg_type + case 'd', + for i=1:length(cs) + c = cs(i); + if c ~= except + lam = lam .* msg{n}.lambda_from_child{i}; + end + end + case 'g', + if isinf(lam.precision) % isfield(lam, 'observed_val') + return; % pass on the observed msg + end + for i=1:length(cs) + c = cs(i); + if c ~= except + m = msg{n}.lambda_from_child{i}; + lam.precision = lam.precision + m.precision; + lam.info_state = lam.info_state + m.info_state; + end + end +end + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/tree_protocol.m b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/tree_protocol.m new file mode 100644 index 00000000..b0ba2fc8 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@pearl_inf_engine/private/tree_protocol.m @@ -0,0 +1,71 @@ +function msg = tree_protocol(engine, evidence, msg) + +bnet = bnet_from_engine(engine); +N = length(bnet.dag); + +% Send messages from leaves to root +for i=1:N-1 + n = engine.postorder(i); + above = parents(engine.adj_mat, n); + msg = send_msgs_to_some_neighbors(n, msg, above, bnet, engine.child_index, engine.parent_index, ... + engine.msg_type, evidence); +end + +% Process root +n = engine.root; +cs = children(bnet.dag, n); +%msg{n}.lambda = compute_lambda(n, cs, msg, engine.msg_type); +msg{n}.lambda = prod_lambda_msgs(n, cs, msg, engine.msg_type); +ps = parents(bnet.dag, n); +msg{n}.pi = CPD_to_pi(bnet.CPD{bnet.equiv_class(n)}, engine.msg_type, n, ps, msg, evidence); + +% Send messages from root to leaves +for i=1:N + n = engine.preorder(i); + below = children(engine.adj_mat, n); + msg = send_msgs_to_some_neighbors(n, msg, below, bnet, engine.child_index, engine.parent_index, ... + engine.msg_type, evidence); +end + + +%%%%%%%%%% + +function msg = send_msgs_to_some_neighbors(n, msg, valid_nbrs, bnet, child_index, parent_index, ... + msg_type, evidence) + +verbose = 0; + +ns = bnet.node_sizes; +dag = bnet.dag; +e = bnet.equiv_class(n); +CPD = bnet.CPD{e}; + + +cs = children(dag, n); +%msg{n}.lambda = compute_lambda(n, cs, msg); +msg{n}.lambda = prod_lambda_msgs(n, cs, msg, msg_type); +if verbose, fprintf('%d computes lambda\n', n); display(msg{n}.lambda); end + +ps = parents(dag, n); +msg{n}.pi = CPD_to_pi(CPD, msg_type, n, ps, msg, evidence); +if verbose, fprintf('%d computes pi\n', n); display(msg{n}.pi); end + +ps2 = myintersect(parents(dag, n), valid_nbrs); +for p=ps2(:)' + lam_msg = CPD_to_lambda_msg(CPD, msg_type, n, ps, msg, p, evidence); + j = child_index{p}(n); % n is p's j'th child + msg{p}.lambda_from_child{j} = lam_msg; + if verbose, fprintf('%d sends lambda to %d\n', n, p); display(lam_msg); end +end + +cs2 = myintersect(cs, valid_nbrs); +for c=cs2(:)' + %pi_msg = compute_pi_msg(n, cs, msg, c); + pi_msg = compute_bel(msg_type, msg{n}.pi, prod_lambda_msgs(n, cs, msg, msg_type, c)); + j = parent_index{c}(n); % n is c's j'th parent + msg{c}.pi_from_parent{j} = pi_msg; + if verbose, fprintf('%d sends pi to %d\n', n, c); display(pi_msg); end +end + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/CVS/Entries new file mode 100644 index 00000000..68df5d27 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/CVS/Entries @@ -0,0 +1,4 @@ +/enter_evidence.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// +/quickscore_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002// +D/private//// diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/CVS/Repository new file mode 100644 index 00000000..cdd697e4 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@quickscore_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/enter_evidence.m new file mode 100644 index 00000000..c697264b --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/enter_evidence.m @@ -0,0 +1,19 @@ +function engine = enter_evidence(engine, pos, neg) +% ENTER_EVIDENCE Add evidence to the QMR network +% engine = enter_evidence(engine, pos, neg) +% +% pos = list of leaves that have positive observations +% neg = list of leaves that have negative observations + +% Extract params for the observed findings +obs = myunion(pos, neg); +%inhibit_obs = engine.inhibit(obs, :); +inhibit_obs = engine.inhibit(:,obs)'; +leak_obs = engine.leak(obs); + +% Find what nodes correspond to the original observed leaves +pos2 = find_equiv_posns(pos, obs); +neg2 = find_equiv_posns(neg, obs); +engine.post = quickscore(pos2, neg2, inhibit_obs, engine.prior, leak_obs); +%engine.post = C_quickscore(pos2, neg2, inhibit_obs, engine.prior, leak_obs); + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..e07c04c2 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/marginal_nodes.m @@ -0,0 +1,11 @@ +function m = marginal_nodes(engine, query) +% MARGINAL_NODES Compute the marginal on the specified query nodes (quickscore) +% marginal = marginal_nodes(engine, query) +% +% 'query' must be a single disease (root) node. + +assert(length(query)==1); +p = engine.post(query); +m.T = [1-p p]'; +m.domain = query; + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/CVS/Entries new file mode 100644 index 00000000..6a6a34f0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/CVS/Entries @@ -0,0 +1,6 @@ +/C_quickscore.c/1.1.1.1/Wed May 29 15:59:56 2002// +/nr.h/1.1.1.1/Wed May 29 15:59:56 2002// +/nrutil.c/1.1.1.1/Wed May 29 15:59:56 2002// +/nrutil.h/1.1.1.1/Wed May 29 15:59:56 2002// +/quickscore.m/1.1.1.1/Wed May 29 15:59:56 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/CVS/Repository new file mode 100644 index 00000000..33f7b87e --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@quickscore_inf_engine/private diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/C_quickscore.c b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/C_quickscore.c new file mode 100644 index 00000000..b9b46f04 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/C_quickscore.c @@ -0,0 +1,164 @@ +/* To compile, type "mex C_quickscore.c" */ + +#include <stdio.h> +#include "nrutil.h" +#include "nrutil.c" +#include <math.h> +#include "mex.h" + +#define MAX(X,Y) (X)>(Y)?(X):(Y) + +int two_to_the(int n) +{ + return 1 << n; +} + +void int2bin(int num, int nbits, int bits[]) +{ + int i, mask; + mask = 1 << (nbits-1); /* mask = 0010...0 , where the 1 is in col nbits (rightmost = col 1) */ + for (i = 0; i < nbits; i++) { + bits[i] = ((num & mask) == 0) ? 0 : 1; + num <<= 1; + } +} + + +void quickscore(int ndiseases, int nfindings, const double *fpos, int npos, const double *fneg, int nneg, + const double *inhibit, const double *prior, const double *leak, double *prob) +{ + double *Pon, *Poff, **Uon, **Uoff, **post, *pterm, *ptermOff, *ptermOn, temp, p, myp; + int *bits, nsubsets, *fmask; + int f, d, i, j, si, size_subset, sign; + + Pon = dvector(0, ndiseases); + Poff = dvector(0, ndiseases); + Pon[0] = 1; + Poff[0] = 0; + for (i=1; i <= ndiseases; i++) { + Pon[i] = prior[i-1]; + Poff[i] = 1-Pon[i]; + } + + Uon = dmatrix(0, nfindings-1, 0, ndiseases); + Uoff = dmatrix(0, nfindings-1, 0, ndiseases); + d = 0; + for (f=0; f < nfindings; f++) { + Uon[f][d] = leak[f]; + Uoff[f][d] = leak[f]; + } + for (f=0; f < nfindings; f++) { + for (d=1; d <= ndiseases; d++) { + Uon[f][d] = inhibit[f + nfindings*(d-1)]; + Uoff[f][d] = 1; + } + } + + post = dmatrix(0, ndiseases, 0, 1); + for (d = 0; d <= ndiseases; d++) { + post[d][0] = 0; + post[d][1] = 0; + } + + bits = ivector(0, npos-1); + fmask = ivector(0, nfindings-1); + pterm = dvector(0, ndiseases); + ptermOff = dvector(0, ndiseases); + ptermOn = dvector(0, ndiseases); + + nsubsets = two_to_the(npos); + + for (si = 0; si < nsubsets; si++) { + int2bin(si, npos, bits); + for (i=0; i < nfindings; i++) fmask[i] = 0; + for (i=0; i < nneg; i++) fmask[(int)fneg[i]-1] = 1; + size_subset = 0; + for (i=0; i < npos; i++) { + if (bits[i]) { + size_subset++; + fmask[(int)fpos[i]-1] = 1; + } + } + p = 1; + for (d=0; d <= ndiseases; d++) { + temp = 1; + for (j = 0; j < nfindings; j++) { + if (fmask[j]) temp *= Uoff[j][d]; + } + ptermOff[d] = temp; + + temp = 1; + for (j = 0; j < nfindings; j++) { + if (fmask[j]) temp *= Uon[j][d]; + } + ptermOn[d] = temp; + + pterm[d] = Poff[d]*ptermOff[d] + Pon[d]*ptermOn[d]; + p *= pterm[d]; + } + sign = (int) pow(-1, size_subset); + for (d=0; d <= ndiseases; d++) { + myp = p / pterm[d]; + post[d][0] += sign*(myp * ptermOff[d]); + post[d][1] += sign*(myp * ptermOn[d]); + } + } /* next si */ + + + for (d=0; d <= ndiseases; d++) { + post[d][0] *= Poff[d]; + post[d][1] *= Pon[d]; + } + for (d=0; d <= ndiseases; d++) { + temp = post[d][0] + post[d][1]; + post[d][0] /= temp; + post[d][1] /= temp; + if (d>0) { prob[d-1] = post[d][1]; } + } + + + free_dvector(Pon, 0, ndiseases); + free_dvector(Poff, 0, ndiseases); + free_dmatrix(Uon, 0, nfindings-1, 0, ndiseases); + free_dmatrix(Uoff, 0, nfindings-1, 0, ndiseases); + free_dmatrix(post, 0, ndiseases, 0, 1); + free_ivector(bits, 0, npos-1); + free_ivector(fmask, 0, nfindings-1); + free_dvector(pterm, 0, ndiseases); + free_dvector(ptermOff, 0, ndiseases); + free_dvector(ptermOn, 0, ndiseases); +} + + +void mexFunction( + int nlhs, mxArray *plhs[], + int nrhs, const mxArray *prhs[] + ) +{ + double *fpos, *fneg, *inhibit, *prior, *leak, *prob; + int npos, nneg, ndiseases, nfindings; + double *p; + + /* read the input args */ + fpos = mxGetPr(prhs[0]); + npos = MAX(mxGetM(prhs[0]), mxGetN(prhs[0])); + + fneg = mxGetPr(prhs[1]); + nneg = MAX(mxGetM(prhs[1]), mxGetN(prhs[1])); + + inhibit = mxGetPr(prhs[2]); /* inhibit(finding, disease) */ + nfindings = mxGetM(prhs[2]); + ndiseases = mxGetN(prhs[2]); + + prior = mxGetPr(prhs[3]); + + leak = mxGetPr(prhs[4]); + + + /* set the output pointers */ + plhs[0] = mxCreateDoubleMatrix(1, ndiseases, mxREAL); + prob = mxGetPr(plhs[0]); + + quickscore(ndiseases, nfindings, fpos, npos, fneg, nneg, inhibit, prior, leak, prob); +} + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/nr.h b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/nr.h new file mode 100644 index 00000000..a7751566 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/nr.h @@ -0,0 +1,536 @@ +/* CAUTION: This is the ANSI C (only) version of the Numerical Recipes + utility file nr.h. Do not confuse this file with the same-named + file nr.h that is supplied in the 'misc' subdirectory. + *That* file is the one from the book, and contains both ANSI and + traditional K&R versions, along with #ifdef macros to select the + correct version. *This* file contains only ANSI C. */ + +#ifndef _NR_H_ +#define _NR_H_ + +#ifndef _FCOMPLEX_DECLARE_T_ +typedef struct FCOMPLEX {float r,i;} fcomplex; +#define _FCOMPLEX_DECLARE_T_ +#endif /* _FCOMPLEX_DECLARE_T_ */ + +#ifndef _ARITHCODE_DECLARE_T_ +typedef struct { + unsigned long *ilob,*iupb,*ncumfq,jdif,nc,minint,nch,ncum,nrad; +} arithcode; +#define _ARITHCODE_DECLARE_T_ +#endif /* _ARITHCODE_DECLARE_T_ */ + +#ifndef _HUFFCODE_DECLARE_T_ +typedef struct { + unsigned long *icod,*ncod,*left,*right,nch,nodemax; +} huffcode; +#define _HUFFCODE_DECLARE_T_ +#endif /* _HUFFCODE_DECLARE_T_ */ + +#include <stdio.h> + +void addint(double **uf, double **uc, double **res, int nf); +void airy(float x, float *ai, float *bi, float *aip, float *bip); +void amebsa(float **p, float y[], int ndim, float pb[], float *yb, + float ftol, float (*funk)(float []), int *iter, float temptr); +void amoeba(float **p, float y[], int ndim, float ftol, + float (*funk)(float []), int *iter); +float amotry(float **p, float y[], float psum[], int ndim, + float (*funk)(float []), int ihi, float fac); +float amotsa(float **p, float y[], float psum[], int ndim, float pb[], + float *yb, float (*funk)(float []), int ihi, float *yhi, float fac); +void anneal(float x[], float y[], int iorder[], int ncity); +double anorm2(double **a, int n); +void arcmak(unsigned long nfreq[], unsigned long nchh, unsigned long nradd, + arithcode *acode); +void arcode(unsigned long *ich, unsigned char **codep, unsigned long *lcode, + unsigned long *lcd, int isign, arithcode *acode); +void arcsum(unsigned long iin[], unsigned long iout[], unsigned long ja, + int nwk, unsigned long nrad, unsigned long nc); +void asolve(unsigned long n, double b[], double x[], int itrnsp); +void atimes(unsigned long n, double x[], double r[], int itrnsp); +void avevar(float data[], unsigned long n, float *ave, float *var); +void balanc(float **a, int n); +void banbks(float **a, unsigned long n, int m1, int m2, float **al, + unsigned long indx[], float b[]); +void bandec(float **a, unsigned long n, int m1, int m2, float **al, + unsigned long indx[], float *d); +void banmul(float **a, unsigned long n, int m1, int m2, float x[], float b[]); +void bcucof(float y[], float y1[], float y2[], float y12[], float d1, + float d2, float **c); +void bcuint(float y[], float y1[], float y2[], float y12[], + float x1l, float x1u, float x2l, float x2u, float x1, + float x2, float *ansy, float *ansy1, float *ansy2); +void beschb(double x, double *gam1, double *gam2, double *gampl, + double *gammi); +float bessi(int n, float x); +float bessi0(float x); +float bessi1(float x); +void bessik(float x, float xnu, float *ri, float *rk, float *rip, + float *rkp); +float bessj(int n, float x); +float bessj0(float x); +float bessj1(float x); +void bessjy(float x, float xnu, float *rj, float *ry, float *rjp, + float *ryp); +float bessk(int n, float x); +float bessk0(float x); +float bessk1(float x); +float bessy(int n, float x); +float bessy0(float x); +float bessy1(float x); +float beta(float z, float w); +float betacf(float a, float b, float x); +float betai(float a, float b, float x); +float bico(int n, int k); +void bksub(int ne, int nb, int jf, int k1, int k2, float ***c); +float bnldev(float pp, int n, long *idum); +float brent(float ax, float bx, float cx, + float (*f)(float), float tol, float *xmin); +float brent_arg(float ax, float bx, float cx, + float (*f)(float, void*), float tol, float *xmin, void *arg); +void broydn(float x[], int n, int *check, + void (*vecfunc)(int, float [], float [])); +void bsstep(float y[], float dydx[], int nv, float *xx, float htry, + float eps, float yscal[], float *hdid, float *hnext, + void (*derivs)(float, float [], float [])); +void caldat(long julian, int *mm, int *id, int *iyyy); +void chder(float a, float b, float c[], float cder[], int n); +float chebev(float a, float b, float c[], int m, float x); +void chebft(float a, float b, float c[], int n, float (*func)(float)); +void chebpc(float c[], float d[], int n); +void chint(float a, float b, float c[], float cint[], int n); +float chixy(float bang); +void choldc(float **a, int n, float p[]); +void cholsl(float **a, int n, float p[], float b[], float x[]); +void chsone(float bins[], float ebins[], int nbins, int knstrn, + float *df, float *chsq, float *prob); +void chstwo(float bins1[], float bins2[], int nbins, int knstrn, + float *df, float *chsq, float *prob); +void cisi(float x, float *ci, float *si); +void cntab1(int **nn, int ni, int nj, float *chisq, + float *df, float *prob, float *cramrv, float *ccc); +void cntab2(int **nn, int ni, int nj, float *h, float *hx, float *hy, + float *hygx, float *hxgy, float *uygx, float *uxgy, float *uxy); +void convlv(float data[], unsigned long n, float respns[], unsigned long m, + int isign, float ans[]); +void copy(double **aout, double **ain, int n); +void correl(float data1[], float data2[], unsigned long n, float ans[]); +void cosft(float y[], int n, int isign); +void cosft1(float y[], int n); +void cosft2(float y[], int n, int isign); +void covsrt(float **covar, int ma, int ia[], int mfit); +void crank(unsigned long n, float w[], float *s); +void cyclic(float a[], float b[], float c[], float alpha, float beta, + float r[], float x[], unsigned long n); +void daub4(float a[], unsigned long n, int isign); +float dawson(float x); +float dbrent(float ax, float bx, float cx, + float (*f)(float), float (*df)(float), float tol, float *xmin); +void ddpoly(float c[], int nc, float x, float pd[], int nd); +int decchk(char string[], int n, char *ch); +void derivs(float x, float y[], float dydx[]); +float df1dim(float x); +void dfour1(double data[], unsigned long nn, int isign); +void dfpmin(float p[], int n, float gtol, int *iter, float *fret, + float (*func)(float []), void (*dfunc)(float [], float [])); +float dfridr(float (*func)(float), float x, float h, float *err); +void dftcor(float w, float delta, float a, float b, float endpts[], + float *corre, float *corim, float *corfac); +void dftint(float (*func)(float), float a, float b, float w, + float *cosint, float *sinint); +void difeq(int k, int k1, int k2, int jsf, int is1, int isf, + int indexv[], int ne, float **s, float **y); +void dlinmin(float p[], float xi[], int n, float *fret, + float (*func)(float []), void (*dfunc)(float [], float[])); +double dpythag(double a, double b); +void drealft(double data[], unsigned long n, int isign); +void dsprsax(double sa[], unsigned long ija[], double x[], double b[], + unsigned long n); +void dsprstx(double sa[], unsigned long ija[], double x[], double b[], + unsigned long n); +void dsvbksb(double **u, double w[], double **v, int m, int n, double b[], + double x[]); +void dsvdcmp(double **a, int m, int n, double w[], double **v); +void eclass(int nf[], int n, int lista[], int listb[], int m); +void eclazz(int nf[], int n, int (*equiv)(int, int)); +float ei(float x); +void eigsrt(float d[], float **v, int n); +float elle(float phi, float ak); +float ellf(float phi, float ak); +float ellpi(float phi, float en, float ak); +void elmhes(float **a, int n); +float erfcc(float x); +float erff(float x); +float erffc(float x); +void eulsum(float *sum, float term, int jterm, float wksp[]); +float evlmem(float fdt, float d[], int m, float xms); +float expdev(long *idum); +float expint(int n, float x); +float f1(float x); +float f1dim(float x); +float f1dim_arg(float x, void *arg); +float f2(float y); +float f3(float z); +float factln(int n); +float factrl(int n); +void fasper(float x[], float y[], unsigned long n, float ofac, float hifac, + float wk1[], float wk2[], unsigned long nwk, unsigned long *nout, + unsigned long *jmax, float *prob); +void fdjac(int n, float x[], float fvec[], float **df, + void (*vecfunc)(int, float [], float [])); +void fgauss(float x, float a[], float *y, float dyda[], int na); +void fill0(double **u, int n); +void fit(float x[], float y[], int ndata, float sig[], int mwt, + float *a, float *b, float *siga, float *sigb, float *chi2, float *q); +void fitexy(float x[], float y[], int ndat, float sigx[], float sigy[], + float *a, float *b, float *siga, float *sigb, float *chi2, float *q); +void fixrts(float d[], int m); +void fleg(float x, float pl[], int nl); +void flmoon(int n, int nph, long *jd, float *frac); +float fmin(float x[]); +void four1(float data[], unsigned long nn, int isign); +void fourew(FILE *file[5], int *na, int *nb, int *nc, int *nd); +void fourfs(FILE *file[5], unsigned long nn[], int ndim, int isign); +void fourn(float data[], unsigned long nn[], int ndim, int isign); +void fpoly(float x, float p[], int np); +void fred2(int n, float a, float b, float t[], float f[], float w[], + float (*g)(float), float (*ak)(float, float)); +float fredin(float x, int n, float a, float b, float t[], float f[], float w[], + float (*g)(float), float (*ak)(float, float)); +void frenel(float x, float *s, float *c); +void frprmn(float p[], int n, float ftol, int *iter, float *fret, + float (*func)(float []), void (*dfunc)(float [], float [])); +void frprmn_arg(float p[], int n, float ftol, int *iter, float *fret, + float (*func)(float [], void*), void (*dfunc)(float [], float [], void*), void* arg); +void ftest(float data1[], unsigned long n1, float data2[], unsigned long n2, + float *f, float *prob); +float gamdev(int ia, long *idum); +float gammln(float xx); +float gammp(float a, float x); +float gammq(float a, float x); +float gasdev(long *idum); +void gaucof(int n, float a[], float b[], float amu0, float x[], float w[]); +void gauher(float x[], float w[], int n); +void gaujac(float x[], float w[], int n, float alf, float bet); +void gaulag(float x[], float w[], int n, float alf); +void gauleg(float x1, float x2, float x[], float w[], int n); +void gaussj(float **a, int n, float **b, int m); +void gcf(float *gammcf, float a, float x, float *gln); +float golden(float ax, float bx, float cx, float (*f)(float), float tol, + float *xmin); +void gser(float *gamser, float a, float x, float *gln); +void hpsel(unsigned long m, unsigned long n, float arr[], float heap[]); +void hpsort(unsigned long n, float ra[]); +void hqr(float **a, int n, float wr[], float wi[]); +void hufapp(unsigned long index[], unsigned long nprob[], unsigned long n, + unsigned long i); +void hufdec(unsigned long *ich, unsigned char *code, unsigned long lcode, + unsigned long *nb, huffcode *hcode); +void hufenc(unsigned long ich, unsigned char **codep, unsigned long *lcode, + unsigned long *nb, huffcode *hcode); +void hufmak(unsigned long nfreq[], unsigned long nchin, unsigned long *ilong, + unsigned long *nlong, huffcode *hcode); +void hunt(float xx[], unsigned long n, float x, unsigned long *jlo); +void hypdrv(float s, float yy[], float dyyds[]); +fcomplex hypgeo(fcomplex a, fcomplex b, fcomplex c, fcomplex z); +void hypser(fcomplex a, fcomplex b, fcomplex c, fcomplex z, + fcomplex *series, fcomplex *deriv); +unsigned short icrc(unsigned short crc, unsigned char *bufptr, + unsigned long len, short jinit, int jrev); +unsigned short icrc1(unsigned short crc, unsigned char onech); +unsigned long igray(unsigned long n, int is); +void iindexx(unsigned long n, long arr[], unsigned long indx[]); +void indexx(unsigned long n, float arr[], unsigned long indx[]); +void interp(double **uf, double **uc, int nf); +int irbit1(unsigned long *iseed); +int irbit2(unsigned long *iseed); +void jacobi(float **a, int n, float d[], float **v, int *nrot); +void jacobn(float x, float y[], float dfdx[], float **dfdy, int n); +long julday(int mm, int id, int iyyy); +void kendl1(float data1[], float data2[], unsigned long n, float *tau, float *z, + float *prob); +void kendl2(float **tab, int i, int j, float *tau, float *z, float *prob); +void kermom(double w[], double y, int m); +void ks2d1s(float x1[], float y1[], unsigned long n1, + void (*quadvl)(float, float, float *, float *, float *, float *), + float *d1, float *prob); +void ks2d2s(float x1[], float y1[], unsigned long n1, float x2[], float y2[], + unsigned long n2, float *d, float *prob); +void ksone(float data[], unsigned long n, float (*func)(float), float *d, + float *prob); +void kstwo(float data1[], unsigned long n1, float data2[], unsigned long n2, + float *d, float *prob); +void laguer(fcomplex a[], int m, fcomplex *x, int *its); +void lfit(float x[], float y[], float sig[], int ndat, float a[], int ia[], + int ma, float **covar, float *chisq, void (*funcs)(float, float [], int)); +void linbcg(unsigned long n, double b[], double x[], int itol, double tol, + int itmax, int *iter, double *err); +void linmin(float p[], float xi[], int n, float *fret, + float (*func)(float [])); +void linmin_arg(float p[], float xi[], int n, float *fret, + float (*func)(float [], void*), void *arg); +void lnsrch(int n, float xold[], float fold, float g[], float p[], float x[], + float *f, float stpmax, int *check, float (*func)(float [])); +void load(float x1, float v[], float y[]); +void load1(float x1, float v1[], float y[]); +void load2(float x2, float v2[], float y[]); +void locate(float xx[], unsigned long n, float x, unsigned long *j); +void lop(double **out, double **u, int n); +void lubksb(float **a, int n, int *indx, float b[]); +void ludcmp(float **a, int n, int *indx, float *d); +void machar(int *ibeta, int *it, int *irnd, int *ngrd, + int *machep, int *negep, int *iexp, int *minexp, int *maxexp, + float *eps, float *epsneg, float *xmin, float *xmax); +void matadd(double **a, double **b, double **c, int n); +void matsub(double **a, double **b, double **c, int n); +void medfit(float x[], float y[], int ndata, float *a, float *b, float *abdev); +void memcof(float data[], int n, int m, float *xms, float d[]); +int metrop(float de, float t); +void mgfas(double **u, int n, int maxcyc); +void mglin(double **u, int n, int ncycle); +float midexp(float (*funk)(float), float aa, float bb, int n); +float midinf(float (*funk)(float), float aa, float bb, int n); +float midpnt(float (*func)(float), float a, float b, int n); +float midsql(float (*funk)(float), float aa, float bb, int n); +float midsqu(float (*funk)(float), float aa, float bb, int n); +void miser(float (*func)(float []), float regn[], int ndim, unsigned long npts, + float dith, float *ave, float *var); +void mmid(float y[], float dydx[], int nvar, float xs, float htot, + int nstep, float yout[], void (*derivs)(float, float[], float[])); +void mnbrak(float *ax, float *bx, float *cx, float *fa, float *fb, + float *fc, float (*func)(float)); +void mnbrak_arg(float *ax, float *bx, float *cx, float *fa, float *fb, + float *fc, float (*func)(float, void*), void *arg); +void mnewt(int ntrial, float x[], int n, float tolx, float tolf); +void moment(float data[], int n, float *ave, float *adev, float *sdev, + float *var, float *skew, float *curt); +void mp2dfr(unsigned char a[], unsigned char s[], int n, int *m); +void mpadd(unsigned char w[], unsigned char u[], unsigned char v[], int n); +void mpdiv(unsigned char q[], unsigned char r[], unsigned char u[], + unsigned char v[], int n, int m); +void mpinv(unsigned char u[], unsigned char v[], int n, int m); +void mplsh(unsigned char u[], int n); +void mpmov(unsigned char u[], unsigned char v[], int n); +void mpmul(unsigned char w[], unsigned char u[], unsigned char v[], int n, + int m); +void mpneg(unsigned char u[], int n); +void mppi(int n); +void mprove(float **a, float **alud, int n, int indx[], float b[], + float x[]); +void mpsad(unsigned char w[], unsigned char u[], int n, int iv); +void mpsdv(unsigned char w[], unsigned char u[], int n, int iv, int *ir); +void mpsmu(unsigned char w[], unsigned char u[], int n, int iv); +void mpsqrt(unsigned char w[], unsigned char u[], unsigned char v[], int n, + int m); +void mpsub(int *is, unsigned char w[], unsigned char u[], unsigned char v[], + int n); +void mrqcof(float x[], float y[], float sig[], int ndata, float a[], + int ia[], int ma, float **alpha, float beta[], float *chisq, + void (*funcs)(float, float [], float *, float [], int)); +void mrqmin(float x[], float y[], float sig[], int ndata, float a[], + int ia[], int ma, float **covar, float **alpha, float *chisq, + void (*funcs)(float, float [], float *, float [], int), float *alamda); +void newt(float x[], int n, int *check, + void (*vecfunc)(int, float [], float [])); +void odeint(float ystart[], int nvar, float x1, float x2, + float eps, float h1, float hmin, int *nok, int *nbad, + void (*derivs)(float, float [], float []), + void (*rkqs)(float [], float [], int, float *, float, float, + float [], float *, float *, void (*)(float, float [], float []))); +void orthog(int n, float anu[], float alpha[], float beta[], float a[], + float b[]); +void pade(double cof[], int n, float *resid); +void pccheb(float d[], float c[], int n); +void pcshft(float a, float b, float d[], int n); +void pearsn(float x[], float y[], unsigned long n, float *r, float *prob, + float *z); +void period(float x[], float y[], int n, float ofac, float hifac, + float px[], float py[], int np, int *nout, int *jmax, float *prob); +void piksr2(int n, float arr[], float brr[]); +void piksrt(int n, float arr[]); +void pinvs(int ie1, int ie2, int je1, int jsf, int jc1, int k, + float ***c, float **s); +float plgndr(int l, int m, float x); +float poidev(float xm, long *idum); +void polcoe(float x[], float y[], int n, float cof[]); +void polcof(float xa[], float ya[], int n, float cof[]); +void poldiv(float u[], int n, float v[], int nv, float q[], float r[]); +void polin2(float x1a[], float x2a[], float **ya, int m, int n, + float x1, float x2, float *y, float *dy); +void polint(float xa[], float ya[], int n, float x, float *y, float *dy); +void powell(float p[], float **xi, int n, float ftol, int *iter, float *fret, + float (*func)(float [])); +void predic(float data[], int ndata, float d[], int m, float future[], int nfut); +float probks(float alam); +void psdes(unsigned long *lword, unsigned long *irword); +void pwt(float a[], unsigned long n, int isign); +void pwtset(int n); +float pythag(float a, float b); +void pzextr(int iest, float xest, float yest[], float yz[], float dy[], + int nv); +float qgaus(float (*func)(float), float a, float b); +void qrdcmp(float **a, int n, float *c, float *d, int *sing); +float qromb(float (*func)(float), float a, float b); +float qromo(float (*func)(float), float a, float b, + float (*choose)(float (*)(float), float, float, int)); +void qroot(float p[], int n, float *b, float *c, float eps); +void qrsolv(float **a, int n, float c[], float d[], float b[]); +void qrupdt(float **r, float **qt, int n, float u[], float v[]); +float qsimp(float (*func)(float), float a, float b); +float qtrap(float (*func)(float), float a, float b); +float quad3d(float (*func)(float, float, float), float x1, float x2); +void quadct(float x, float y, float xx[], float yy[], unsigned long nn, + float *fa, float *fb, float *fc, float *fd); +void quadmx(float **a, int n); +void quadvl(float x, float y, float *fa, float *fb, float *fc, float *fd); +float ran0(long *idum); +float ran1(long *idum); +float ran2(long *idum); +float ran3(long *idum); +float ran4(long *idum); +void rank(unsigned long n, unsigned long indx[], unsigned long irank[]); +void ranpt(float pt[], float regn[], int n); +void ratint(float xa[], float ya[], int n, float x, float *y, float *dy); +void ratlsq(double (*fn)(double), double a, double b, int mm, int kk, + double cof[], double *dev); +double ratval(double x, double cof[], int mm, int kk); +float rc(float x, float y); +float rd(float x, float y, float z); +void realft(float data[], unsigned long n, int isign); +void rebin(float rc, int nd, float r[], float xin[], float xi[]); +void red(int iz1, int iz2, int jz1, int jz2, int jm1, int jm2, int jmf, + int ic1, int jc1, int jcf, int kc, float ***c, float **s); +void relax(double **u, double **rhs, int n); +void relax2(double **u, double **rhs, int n); +void resid(double **res, double **u, double **rhs, int n); +float revcst(float x[], float y[], int iorder[], int ncity, int n[]); +void reverse(int iorder[], int ncity, int n[]); +float rf(float x, float y, float z); +float rj(float x, float y, float z, float p); +void rk4(float y[], float dydx[], int n, float x, float h, float yout[], + void (*derivs)(float, float [], float [])); +void rkck(float y[], float dydx[], int n, float x, float h, + float yout[], float yerr[], void (*derivs)(float, float [], float [])); +void rkdumb(float vstart[], int nvar, float x1, float x2, int nstep, + void (*derivs)(float, float [], float [])); +void rkqs(float y[], float dydx[], int n, float *x, + float htry, float eps, float yscal[], float *hdid, float *hnext, + void (*derivs)(float, float [], float [])); +void rlft3(float ***data, float **speq, unsigned long nn1, + unsigned long nn2, unsigned long nn3, int isign); +float rofunc(float b); +void rotate(float **r, float **qt, int n, int i, float a, float b); +void rsolv(float **a, int n, float d[], float b[]); +void rstrct(double **uc, double **uf, int nc); +float rtbis(float (*func)(float), float x1, float x2, float xacc); +float rtflsp(float (*func)(float), float x1, float x2, float xacc); +float rtnewt(void (*funcd)(float, float *, float *), float x1, float x2, + float xacc); +float rtsafe(void (*funcd)(float, float *, float *), float x1, float x2, + float xacc); +float rtsec(float (*func)(float), float x1, float x2, float xacc); +void rzextr(int iest, float xest, float yest[], float yz[], float dy[], int nv); +void savgol(float c[], int np, int nl, int nr, int ld, int m); +void score(float xf, float y[], float f[]); +void scrsho(float (*fx)(float)); +float select(unsigned long k, unsigned long n, float arr[]); +float selip(unsigned long k, unsigned long n, float arr[]); +void shell(unsigned long n, float a[]); +void shoot(int n, float v[], float f[]); +void shootf(int n, float v[], float f[]); +void simp1(float **a, int mm, int ll[], int nll, int iabf, int *kp, + float *bmax); +void simp2(float **a, int n, int l2[], int nl2, int *ip, int kp, float *q1); +void simp3(float **a, int i1, int k1, int ip, int kp); +void simplx(float **a, int m, int n, int m1, int m2, int m3, int *icase, + int izrov[], int iposv[]); +void simpr(float y[], float dydx[], float dfdx[], float **dfdy, + int n, float xs, float htot, int nstep, float yout[], + void (*derivs)(float, float [], float [])); +void sinft(float y[], int n); +void slvsm2(double **u, double **rhs); +void slvsml(double **u, double **rhs); +void sncndn(float uu, float emmc, float *sn, float *cn, float *dn); +double snrm(unsigned long n, double sx[], int itol); +void sobseq(int *n, float x[]); +void solvde(int itmax, float conv, float slowc, float scalv[], + int indexv[], int ne, int nb, int m, float **y, float ***c, float **s); +void sor(double **a, double **b, double **c, double **d, double **e, + double **f, double **u, int jmax, double rjac); +void sort(unsigned long n, float arr[]); +void sort2(unsigned long n, float arr[], float brr[]); +void sort3(unsigned long n, float ra[], float rb[], float rc[]); +void spctrm(FILE *fp, float p[], int m, int k, int ovrlap); +void spear(float data1[], float data2[], unsigned long n, float *d, float *zd, + float *probd, float *rs, float *probrs); +void sphbes(int n, float x, float *sj, float *sy, float *sjp, float *syp); +void splie2(float x1a[], float x2a[], float **ya, int m, int n, float **y2a); +void splin2(float x1a[], float x2a[], float **ya, float **y2a, int m, int n, + float x1, float x2, float *y); +void spline(float x[], float y[], int n, float yp1, float ypn, float y2[]); +void splint(float xa[], float ya[], float y2a[], int n, float x, float *y); +void spread(float y, float yy[], unsigned long n, float x, int m); +void sprsax(float sa[], unsigned long ija[], float x[], float b[], + unsigned long n); +void sprsin(float **a, int n, float thresh, unsigned long nmax, float sa[], + unsigned long ija[]); +void sprspm(float sa[], unsigned long ija[], float sb[], unsigned long ijb[], + float sc[], unsigned long ijc[]); +void sprstm(float sa[], unsigned long ija[], float sb[], unsigned long ijb[], + float thresh, unsigned long nmax, float sc[], unsigned long ijc[]); +void sprstp(float sa[], unsigned long ija[], float sb[], unsigned long ijb[]); +void sprstx(float sa[], unsigned long ija[], float x[], float b[], + unsigned long n); +void stifbs(float y[], float dydx[], int nv, float *xx, + float htry, float eps, float yscal[], float *hdid, float *hnext, + void (*derivs)(float, float [], float [])); +void stiff(float y[], float dydx[], int n, float *x, + float htry, float eps, float yscal[], float *hdid, float *hnext, + void (*derivs)(float, float [], float [])); +void stoerm(float y[], float d2y[], int nv, float xs, + float htot, int nstep, float yout[], + void (*derivs)(float, float [], float [])); +void svbksb(float **u, float w[], float **v, int m, int n, float b[], + float x[]); +void svdcmp(float **a, int m, int n, float w[], float **v); +void svdfit(float x[], float y[], float sig[], int ndata, float a[], + int ma, float **u, float **v, float w[], float *chisq, + void (*funcs)(float, float [], int)); +void svdvar(float **v, int ma, float w[], float **cvm); +void toeplz(float r[], float x[], float y[], int n); +void tptest(float data1[], float data2[], unsigned long n, float *t, float *prob); +void tqli(float d[], float e[], int n, float **z); +float trapzd(float (*func)(float), float a, float b, int n); +void tred2(float **a, int n, float d[], float e[]); +void tridag(float a[], float b[], float c[], float r[], float u[], + unsigned long n); +float trncst(float x[], float y[], int iorder[], int ncity, int n[]); +void trnspt(int iorder[], int ncity, int n[]); +void ttest(float data1[], unsigned long n1, float data2[], unsigned long n2, + float *t, float *prob); +void tutest(float data1[], unsigned long n1, float data2[], unsigned long n2, + float *t, float *prob); +void twofft(float data1[], float data2[], float fft1[], float fft2[], + unsigned long n); +void vander(double x[], double w[], double q[], int n); +void vegas(float regn[], int ndim, float (*fxn)(float [], float), int init, + unsigned long ncall, int itmx, int nprn, float *tgral, float *sd, + float *chi2a); +void voltra(int n, int m, float t0, float h, float *t, float **f, + float (*g)(int, float), float (*ak)(int, int, float, float)); +void wt1(float a[], unsigned long n, int isign, + void (*wtstep)(float [], unsigned long, int)); +void wtn(float a[], unsigned long nn[], int ndim, int isign, + void (*wtstep)(float [], unsigned long, int)); +void wwghts(float wghts[], int n, float h, + void (*kermom)(double [], double ,int)); +int zbrac(float (*func)(float), float *x1, float *x2); +void zbrak(float (*fx)(float), float x1, float x2, int n, float xb1[], + float xb2[], int *nb); +float zbrent(float (*func)(float), float x1, float x2, float tol); +void zrhqr(float a[], int m, float rtr[], float rti[]); +float zriddr(float (*func)(float), float x1, float x2, float xacc); +void zroots(fcomplex a[], int m, fcomplex roots[], int polish); + +#endif /* _NR_H_ */ diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/nrutil.c b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/nrutil.c new file mode 100644 index 00000000..059dce54 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/nrutil.c @@ -0,0 +1,321 @@ +/* CAUTION: This is the ANSI C (only) version of the Numerical Recipes + utility file nrutil.c. Do not confuse this file with the same-named + file nrutil.c that is supplied in the 'misc' subdirectory. + *That* file is the one from the book, and contains both ANSI and + traditional K&R versions, along with #ifdef macros to select the + correct version. *This* file contains only ANSI C. */ + +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#define NR_END 1 +#define FREE_ARG char* + +void nrerror(char error_text[]) +/* Numerical Recipes standard error handler */ +{ + fprintf(stderr,"Numerical Recipes run-time error...\n"); + fprintf(stderr,"%s\n",error_text); + fprintf(stderr,"...now exiting to system...\n"); + exit(1); +} + +float *vector(long nl, long nh) +/* allocate a float vector with subscript range v[nl..nh] */ +{ + float *v; + + v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float))); + if (!v) nrerror("allocation failure in vector()"); + return v-nl+NR_END; +} + +int *ivector(long nl, long nh) +/* allocate an int vector with subscript range v[nl..nh] */ +{ + int *v; + + v=(int *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(int))); + if (!v) nrerror("allocation failure in ivector()"); + return v-nl+NR_END; +} + +unsigned char *cvector(long nl, long nh) +/* allocate an unsigned char vector with subscript range v[nl..nh] */ +{ + unsigned char *v; + + v=(unsigned char *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(unsigned char))); + if (!v) nrerror("allocation failure in cvector()"); + return v-nl+NR_END; +} + +unsigned long *lvector(long nl, long nh) +/* allocate an unsigned long vector with subscript range v[nl..nh] */ +{ + unsigned long *v; + + v=(unsigned long *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(long))); + if (!v) nrerror("allocation failure in lvector()"); + return v-nl+NR_END; +} + +double *dvector(long nl, long nh) +/* allocate a double vector with subscript range v[nl..nh] */ +{ + double *v; + + v=(double *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(double))); + if (!v) nrerror("allocation failure in dvector()"); + return v-nl+NR_END; +} + +float **matrix(long nrl, long nrh, long ncl, long nch) +/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */ +{ + long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; + float **m; + + /* allocate pointers to rows */ + m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*))); + if (!m) nrerror("allocation failure 1 in matrix()"); + m += NR_END; + m -= nrl; + + /* allocate rows and set pointers to them */ + m[nrl]=(float *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float))); + if (!m[nrl]) nrerror("allocation failure 2 in matrix()"); + m[nrl] += NR_END; + m[nrl] -= ncl; + + for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; + + /* return pointer to array of pointers to rows */ + return m; +} + +double **dmatrix(long nrl, long nrh, long ncl, long nch) +/* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */ +{ + long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; + double **m; + + /* allocate pointers to rows */ + m=(double **) malloc((size_t)((nrow+NR_END)*sizeof(double*))); + if (!m) nrerror("allocation failure 1 in matrix()"); + m += NR_END; + m -= nrl; + + /* allocate rows and set pointers to them */ + m[nrl]=(double *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(double))); + if (!m[nrl]) nrerror("allocation failure 2 in matrix()"); + m[nrl] += NR_END; + m[nrl] -= ncl; + + for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; + + /* return pointer to array of pointers to rows */ + return m; +} + +int **imatrix(long nrl, long nrh, long ncl, long nch) +/* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */ +{ + long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; + int **m; + + /* allocate pointers to rows */ + m=(int **) malloc((size_t)((nrow+NR_END)*sizeof(int*))); + if (!m) nrerror("allocation failure 1 in matrix()"); + m += NR_END; + m -= nrl; + + + /* allocate rows and set pointers to them */ + m[nrl]=(int *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(int))); + if (!m[nrl]) nrerror("allocation failure 2 in matrix()"); + m[nrl] += NR_END; + m[nrl] -= ncl; + + for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; + + /* return pointer to array of pointers to rows */ + return m; +} + +float **submatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch, + long newrl, long newcl) +/* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */ +{ + long i,j,nrow=oldrh-oldrl+1,ncol=oldcl-newcl; + float **m; + + /* allocate array of pointers to rows */ + m=(float **) malloc((size_t) ((nrow+NR_END)*sizeof(float*))); + if (!m) nrerror("allocation failure in submatrix()"); + m += NR_END; + m -= newrl; + + /* set pointers to rows */ + for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+ncol; + + /* return pointer to array of pointers to rows */ + return m; +} + +float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch) +/* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix +declared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1 +and ncol=nch-ncl+1. The routine should be called with the address +&a[0][0] as the first argument. */ +{ + long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1; + float **m; + + /* allocate pointers to rows */ + m=(float **) malloc((size_t) ((nrow+NR_END)*sizeof(float*))); + if (!m) nrerror("allocation failure in convert_matrix()"); + m += NR_END; + m -= nrl; + + /* set pointers to rows */ + m[nrl]=a-ncl; + for(i=1,j=nrl+1;i<nrow;i++,j++) m[j]=m[j-1]+ncol; + /* return pointer to array of pointers to rows */ + return m; +} + +double **convert_dmatrix(double *a, long nrl, long nrh, long ncl, long nch) +/* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix +declared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1 +and ncol=nch-ncl+1. The routine should be called with the address +&a[0][0] as the first argument. */ +{ + long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1; + double **m; + + /* allocate pointers to rows */ + m=(double **) malloc((size_t) ((nrow+NR_END)*sizeof(double*))); + if (!m) nrerror("allocation failure in convert_dmatrix()"); + m += NR_END; + m -= nrl; + + /* set pointers to rows */ + m[nrl]=a-ncl; + for(i=1,j=nrl+1;i<nrow;i++,j++) m[j]=m[j-1]+ncol; + /* return pointer to array of pointers to rows */ + return m; +} + +float ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh) +/* allocate a float 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */ +{ + long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1; + float ***t; + + /* allocate pointers to pointers to rows */ + t=(float ***) malloc((size_t)((nrow+NR_END)*sizeof(float**))); + if (!t) nrerror("allocation failure 1 in f3tensor()"); + t += NR_END; + t -= nrl; + + /* allocate pointers to rows and set pointers to them */ + t[nrl]=(float **) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float*))); + if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()"); + t[nrl] += NR_END; + t[nrl] -= ncl; + + /* allocate rows and set pointers to them */ + t[nrl][ncl]=(float *) malloc((size_t)((nrow*ncol*ndep+NR_END)*sizeof(float))); + if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()"); + t[nrl][ncl] += NR_END; + t[nrl][ncl] -= ndl; + + for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep; + for(i=nrl+1;i<=nrh;i++) { + t[i]=t[i-1]+ncol; + t[i][ncl]=t[i-1][ncl]+ncol*ndep; + for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep; + } + + /* return pointer to array of pointers to rows */ + return t; +} + +void free_vector(float *v, long nl, long nh) +/* free a float vector allocated with vector() */ +{ + free((FREE_ARG) (v+nl-NR_END)); +} + +void free_ivector(int *v, long nl, long nh) +/* free an int vector allocated with ivector() */ +{ + free((FREE_ARG) (v+nl-NR_END)); +} + +void free_cvector(unsigned char *v, long nl, long nh) +/* free an unsigned char vector allocated with cvector() */ +{ + free((FREE_ARG) (v+nl-NR_END)); +} + +void free_lvector(unsigned long *v, long nl, long nh) +/* free an unsigned long vector allocated with lvector() */ +{ + free((FREE_ARG) (v+nl-NR_END)); +} + +void free_dvector(double *v, long nl, long nh) +/* free a double vector allocated with dvector() */ +{ + free((FREE_ARG) (v+nl-NR_END)); +} + +void free_matrix(float **m, long nrl, long nrh, long ncl, long nch) +/* free a float matrix allocated by matrix() */ +{ + free((FREE_ARG) (m[nrl]+ncl-NR_END)); + free((FREE_ARG) (m+nrl-NR_END)); +} + +void free_dmatrix(double **m, long nrl, long nrh, long ncl, long nch) +/* free a double matrix allocated by dmatrix() */ +{ + free((FREE_ARG) (m[nrl]+ncl-NR_END)); + free((FREE_ARG) (m+nrl-NR_END)); +} + +void free_imatrix(int **m, long nrl, long nrh, long ncl, long nch) +/* free an int matrix allocated by imatrix() */ +{ + free((FREE_ARG) (m[nrl]+ncl-NR_END)); + free((FREE_ARG) (m+nrl-NR_END)); +} + +void free_submatrix(float **b, long nrl, long nrh, long ncl, long nch) +/* free a submatrix allocated by submatrix() */ +{ + free((FREE_ARG) (b+nrl-NR_END)); +} + +void free_convert_matrix(float **b, long nrl, long nrh, long ncl, long nch) +/* free a matrix allocated by convert_matrix() */ +{ + free((FREE_ARG) (b+nrl-NR_END)); +} + +void free_convert_dmatrix(double **b, long nrl, long nrh, long ncl, long nch) +/* free a matrix allocated by convert_matrix() */ +{ + free((FREE_ARG) (b+nrl-NR_END)); +} + +void free_f3tensor(float ***t, long nrl, long nrh, long ncl, long nch, + long ndl, long ndh) +/* free a float f3tensor allocated by f3tensor() */ +{ + free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END)); + free((FREE_ARG) (t[nrl]+ncl-NR_END)); + free((FREE_ARG) (t+nrl-NR_END)); +} diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/nrutil.h b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/nrutil.h new file mode 100644 index 00000000..45b1447f --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/nrutil.h @@ -0,0 +1,79 @@ +/* CAUTION: This is the ANSI C (only) version of the Numerical Recipes + utility file nrutil.h. Do not confuse this file with the same-named + file nrutil.h that is supplied in the 'misc' subdirectory. + *That* file is the one from the book, and contains both ANSI and + traditional K&R versions, along with #ifdef macros to select the + correct version. *This* file contains only ANSI C. */ + +#ifndef _NR_UTILS_H_ +#define _NR_UTILS_H_ + +static float sqrarg; +#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg) + +static double dsqrarg; +#define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg) + +static double dmaxarg1,dmaxarg2; +#define DMAX(a,b) (dmaxarg1=(a),dmaxarg2=(b),(dmaxarg1) > (dmaxarg2) ?\ + (dmaxarg1) : (dmaxarg2)) + +static double dminarg1,dminarg2; +#define DMIN(a,b) (dminarg1=(a),dminarg2=(b),(dminarg1) < (dminarg2) ?\ + (dminarg1) : (dminarg2)) + +static float maxarg1,maxarg2; +#define FMAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\ + (maxarg1) : (maxarg2)) + +static float minarg1,minarg2; +#define FMIN(a,b) (minarg1=(a),minarg2=(b),(minarg1) < (minarg2) ?\ + (minarg1) : (minarg2)) + +static long lmaxarg1,lmaxarg2; +#define LMAX(a,b) (lmaxarg1=(a),lmaxarg2=(b),(lmaxarg1) > (lmaxarg2) ?\ + (lmaxarg1) : (lmaxarg2)) + +static long lminarg1,lminarg2; +#define LMIN(a,b) (lminarg1=(a),lminarg2=(b),(lminarg1) < (lminarg2) ?\ + (lminarg1) : (lminarg2)) + +static int imaxarg1,imaxarg2; +#define IMAX(a,b) (imaxarg1=(a),imaxarg2=(b),(imaxarg1) > (imaxarg2) ?\ + (imaxarg1) : (imaxarg2)) + +static int iminarg1,iminarg2; +#define IMIN(a,b) (iminarg1=(a),iminarg2=(b),(iminarg1) < (iminarg2) ?\ + (iminarg1) : (iminarg2)) + +#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a)) + +void nrerror(char error_text[]); +float *vector(long nl, long nh); +int *ivector(long nl, long nh); +unsigned char *cvector(long nl, long nh); +unsigned long *lvector(long nl, long nh); +double *dvector(long nl, long nh); +float **matrix(long nrl, long nrh, long ncl, long nch); +double **dmatrix(long nrl, long nrh, long ncl, long nch); +int **imatrix(long nrl, long nrh, long ncl, long nch); +float **submatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch, + long newrl, long newcl); +float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch); +double **convert_dmatrix(double *a, long nrl, long nrh, long ncl, long nch); +float ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh); +void free_vector(float *v, long nl, long nh); +void free_ivector(int *v, long nl, long nh); +void free_cvector(unsigned char *v, long nl, long nh); +void free_lvector(unsigned long *v, long nl, long nh); +void free_dvector(double *v, long nl, long nh); +void free_matrix(float **m, long nrl, long nrh, long ncl, long nch); +void free_dmatrix(double **m, long nrl, long nrh, long ncl, long nch); +void free_imatrix(int **m, long nrl, long nrh, long ncl, long nch); +void free_submatrix(float **b, long nrl, long nrh, long ncl, long nch); +void free_convert_matrix(float **b, long nrl, long nrh, long ncl, long nch); +void free_convert_dmatrix(double **b, long nrl, long nrh, long ncl, long nch); +void free_f3tensor(float ***t, long nrl, long nrh, long ncl, long nch, + long ndl, long ndh); + +#endif /* _NR_UTILS_H_ */ diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/quickscore.m b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/quickscore.m new file mode 100644 index 00000000..1a9b534a --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/private/quickscore.m @@ -0,0 +1,76 @@ +function prob = quickscore(fpos, fneg, inhibit, prior, leak) +% QUICKSCORE Heckerman's algorithm for BN2O networks. +% prob = quickscore(fpos, fneg, inhibit, prior, leak) +% +% Consider a BN2O (Binary Node 2-layer Noisy-or) network such as QMR with +% dieases on the top and findings on the bottom. (We assume all findings are observed, +% since hidden leaves can be marginalized away.) +% This algorithm takes O(2^|fpos|) time to compute the marginal on all the diseases. +% +% Inputs: +% fpos = the positive findings (a vector of numbers in {1, ..., Nfindings}) +% fneg = the negative findings (a vector of numbers in {1, ..., Nfindings}) +% inhibit(i,j) = inhibition prob. for finding i, disease j, or 1.0 if j is not a parent. +% prior(j) = prior prob. disease j is ON. We assume prior(off) = 1-prior(on). +% leak(i) = inhibition prob. for the leak node for finding i +% +% Output: +% prob(d) = Pr(disease d = on | ev) +% +% For details, see +% - Heckerman, "A tractable inference algorithm for diagnosing multiple diseases", UAI89. +% - Rish and Dechter, "On the impact of causal independence", UCI tech report, 1998. +% +% Note that this algorithm is numerically unstable, since it adds a large number of positive and +% negative terms and hopes that some of them exactly cancel. +% +% For matlab experts, use 'mex' to compile C_quickscore, which has identical behavior to this function. + +[nfindings ndiseases] = size(inhibit); + +% make the first disease be always on, for the leak term +Pon = [1 prior(:)']; +Poff = 1-Pon; +Uon = [leak(:) inhibit]; % U(f,d) = Pr(f=0|d=1) +Uoff = [leak(:) ones(nfindings, ndiseases)]; % Uoff(f,d) = Pr(f=0|d=0) +ndiseases = ndiseases + 1; + +npos = length(fpos); +post = zeros(ndiseases, 2); +% post(d,1) = alpha Pr(d=off), post(d,2) = alpha Pr(d=m) + +FP = length(fpos); +%allbits = logical(dec2bitv(0:(2^FP - 1), FP)); +allbits = logical(ind2subv(2*ones(1,FP), 1:(2^FP))-1); + +for si=1:2^FP + bits = allbits(si,:); + fprime = fpos(bits); + fmask = zeros(1, nfindings); + fmask(fneg)=1; + fmask(fprime)=1; + fmask = logical(fmask); + p = 1; + pterm = zeros(1, ndiseases); + ptermOff = zeros(1, ndiseases); + ptermOn = zeros(1, ndiseases); + for d=1:ndiseases + ptermOff(d) = prod(Uoff(fmask,d)); + ptermOn(d) = prod(Uon(fmask,d)); + pterm(d) = Poff(d)*ptermOff(d) + Pon(d)*ptermOn(d); + end + p = prod(pterm); + sign = (-1)^(length(fprime)); + for d=1:ndiseases + myp = p / pterm(d); + post(d,1) = post(d,1) + sign*(myp * ptermOff(d)); + post(d,2) = post(d,2) + sign*(myp * ptermOn(d)); + end +end + +post(:,1) = post(:,1) .* Poff(:); +post(:,2) = post(:,2) .* Pon(:); +post = mk_stochastic(post); +prob = post(2:end,2)'; % skip the leak term + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/quickscore_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/quickscore_inf_engine.m new file mode 100644 index 00000000..a9463c40 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@quickscore_inf_engine/quickscore_inf_engine.m @@ -0,0 +1,38 @@ +function engine = quickscore_inf_engine(inhibit, leak, prior) +% QUICKSCORE_INF_ENGINE Exact inference for the QMR network +% engine = quickscore_inf_engine(inhibit, leak, prior) +% +% We create an inference engine for QMR-like networks. +% QMR is a bipartite graph, where the top layer contains hidden disease nodes, +% and the bottom later contains observed finding nodes. +% The diseases have Bernoulli CPDs, the findings noisy-or CPDs. +% The original QMR (Quick Medical Reference) network has specific parameter values which we are not +% allowed to release, for commercial reasons. +% +% inhibit(f,d) = inhibition probability on f->d arc for disease d, finding f +% If inhibit(f,d) = 1, there is effectively no arc from d->f +% leak(j) = inhibition prob. on leak node -> finding j arc +% prior(i) = prob. disease i is on +% +% We use exact inference, which takes O(2^P) time, where P is the number of positive findings. +% For details, see +% - Heckerman, "A tractable inference algorithm for diagnosing multiple diseases", UAI 89. +% - Rish and Dechter, "On the impact of causal independence", UCI tech report, 1998. +% Note that this algorithm is numerically unstable, since it adds a large number of positive and +% negative terms and hopes that some of them exactly cancel. +% +% For an interesting variational approximation, see +% - Jaakkola and Jordan, "Variational probabilistic inference and the QMR-DT network", JAIR 10, 1999. +% +% See also +% - "Loopy belief propagation for approximate inference: an empirical study", +% K. Murphy, Y. Weiss and M. Jordan, UAI 99. + +engine.inhibit = inhibit; +engine.leak = leak; +engine.prior = prior; + +% store results here between enter_evidence and marginal_nodes +engine.post = []; + +engine = class(engine, 'quickscore_inf_engine'); % not a child of the inf_engine class! diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Entries new file mode 100644 index 00000000..055aa4df --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Entries @@ -0,0 +1,11 @@ +/README/1.1.1.1/Sun May 11 15:39:50 2003// +/clq_containing_nodes.m/1.1.1.1/Wed May 29 11:59:46 2002// +/enter_evidence.m/1.1.1.1/Wed Mar 12 10:38:00 2003// +/marginal_difclq_nodes.m/1.1.1.1/Fri Feb 21 11:20:32 2003// +/marginal_nodes.m/1.1.1.1/Fri Feb 21 11:13:10 2003// +/marginal_singleclq_nodes.m/1.1.1.1/Wed Jan 29 11:23:58 2003// +/problems.txt/1.1.1.1/Wed May 29 11:59:46 2002// +/push.m/1.1.1.1/Mon Feb 10 15:38:04 2003// +/push_pot_toclique.m/1.1.1.1/Wed May 29 11:59:46 2002// +/stab_cond_gauss_inf_engine.m/1.1.1.1/Fri Mar 28 17:12:42 2003// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Entries.Log b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Entries.Log new file mode 100644 index 00000000..24f16336 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Entries.Log @@ -0,0 +1 @@ +A D/Old//// diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Repository new file mode 100644 index 00000000..849daef7 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Entries new file mode 100644 index 00000000..ce0c4813 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Entries @@ -0,0 +1,2 @@ +/initialize_engine.m/1.1.1.1/Wed May 29 11:59:46 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Repository new file mode 100644 index 00000000..eb292815 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/Old diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_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/@stab_cond_gauss_inf_engine/Old/initialize_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/initialize_engine.m new file mode 100644 index 00000000..6fb51c2e --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/initialize_engine.m @@ -0,0 +1,65 @@ +function [engine, loglik] = initialize_engine(engine) +%initialize +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes(:); +N = length(bnet.dag); + +pot_type = 'scg' +check_for_cd_arcs([], bnet.cnodes, bnet.dag); + +% Evaluate CPDs with evidence, and convert to potentials +pot = cell(1, N); +C = length(engine.cliques); +inited = zeros(1, C); +clpot = cell(1, C); +evidence = cell(1, N); +for n=1:N + fam = family(bnet.dag, n); + e = bnet.equiv_class(n); + pot{n} = CPD_to_scgpot(bnet.CPD{e}, fam, ns, bnet.cnodes, evidence); + cindex = engine.clq_ass_to_node(n); + if inited(cindex) + %clpot{cindex} = direct_combine_pots(clpot{cindex}, pot{n}); + clpot{cindex} = direct_combine_pots(pot{n}, clpot{cindex}); + else + clpot{cindex} = pot{n}; + inited(cindex) = 1; + end +end + +for i=1:C + if inited(i) == 0 + clpot{i} = scgpot([], [], [], []); + end +end + +seppot = cell(C, C); +% separators are is not need to initialize + +% collect to root (node to parents) +for n=engine.postorder(1:end-1) + for p=parents(engine.jtree, n) + [margpot, comppot] = complement_pot(clpot{n}, engine.separator{p,n}); + margpot = marginalize_pot(clpot{n}, engine.separator{p,n}); + clpot{n} = comppot; + %seppot{p, n} = margpot; + clpot{p} = combine_pots(clpot{p}, margpot); + %clpot{p} = combine_pots(margpot, clpot{p}); + end +end + +temppot = clpot; +%temppot = clpot{engine.root}; +for n=engine.preorder + for c=children(engine.jtree, n) + seppot{n,c} = marginalize_pot(temppot{n}, engine.separator{n,c}); + %seppot{n,c} = marginalize_pot(clpot{n}, engine.separator{n,c}); + %clpot{c} = direct_combine_pots(clpot{c}, seppot{n,c}); + temppot{c} = direct_combine_pots(temppot{c}, seppot{n,c}); + end +end + +engine.clpot = clpot; +engine.seppot = seppot; + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/README b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/README new file mode 100644 index 00000000..e905e28c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/README @@ -0,0 +1,12 @@ +% Stable conditional Gaussian inference +% Originally written by Huang, Shan <shan.huang@intel.com> 2001 +% Fixed by Rainer Deventer 2003 + + +@techreport{Lauritzen99, + author = "S. Lauritzen and F. Jensen", + title = "Stable Local Computation with Conditional {G}aussian Distributions", + year = 1999, + number = "R-99-2014", + institution = "Dept. Math. Sciences, Aalborg Univ." +} diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/clq_containing_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/clq_containing_nodes.m new file mode 100644 index 00000000..c64d2bff --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_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/@stab_cond_gauss_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/enter_evidence.m new file mode 100644 index 00000000..4b02fc8f --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/enter_evidence.m @@ -0,0 +1,260 @@ +function [engine, loglik] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE enter evidence to engine including discrete and continuous evidence +% [engine, ll] = enter_evidence(engine, evidence) +% +% ll is always 0, which is wrong. + +if ~isempty(engine.evidence) + bnet = bnet_from_engine(engine); + engine = stab_cond_gauss_inf_engine(bnet); + engine.evidence = evidence; +else + engine.evidence = evidence; + bnet = bnet_from_engine(engine); +end + +engine.evidence = evidence; +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes(:); +observed = ~isemptycell(evidence); +onodes = find(observed); +hnodes = find(isemptycell(evidence)); +cobs = myintersect(bnet.cnodes, onodes); +dobs = myintersect(bnet.dnodes, onodes); + +engine = incorporate_dis_evidence(engine, dobs, evidence); +l = length(cobs); +for i = 1:l + node = cobs(i); + engine = incorporate_singleconts_evidence(engine, node, evidence); +end +clpot = engine.clpot; + +clq_num = length(engine.cliques); +for n=engine.postorder(1:end-1) + for p=parents(engine.jtree, n) + [margpot, comppot] = complement_pot(clpot{n}, engine.separator{p,n}); + clpot{n} = comppot; + clpot{p} = combine_pots(clpot{p}, margpot); + end +end + +temppot = clpot; +for n=engine.preorder + for c=children(engine.jtree, n) + seppot{n,c} = marginalize_pot(temppot{n}, engine.separator{n,c}); + temppot{c} = direct_combine_pots(temppot{c}, seppot{n,c}); + end +end +engine.clpot = clpot; +engine.seppot = seppot; + +[pot,loglik]=normalize_pot(clpot{engine.root}); + +%%%%%%%%%%%%%%%%%% +function engine = incorporate_dis_evidence(engine, donodes, evidence) +l = length(donodes); +for i=donodes(:)' + node = i; + clqid = engine.clq_ass_to_node(node); + pot = struct(engine.clpot{clqid}); + ns = zeros(1, max(pot.domain)); + ns(pot.ddom) = pot.dsizes; + ns(pot.cheaddom) = pot.cheadsizes; + ns(pot.ctaildom) = pot.ctailsizes; + ddom = pot.ddom; + + potcarray = cell(1, pot.dsize); + for j =1:pot.dsize + tpotc = struct(pot.scgpotc{j}); + potcarray{j} = scgcpot(tpotc.cheadsize, tpotc.ctailsize, 0, tpotc.A, tpotc.B, tpotc.C); + end + + if length(ns(ddom)) == 1 + matrix = pot.scgpotc; + else + matrix = reshape(pot.scgpotc,ns(ddom)); + potcarray = reshape(potcarray, ns(ddom)); + end + + map = find_equiv_posns(node, ddom); + vals = cat(1, evidence{node}); + index = mk_multi_index(length(ddom), map, vals); + potcarray(index{:}) = matrix(index{:}); + potcarray = potcarray(:); + %keyboard; + engine.clpot{clqid} = scgpot(pot.ddom, pot.cheaddom, pot.ctaildom, ns, potcarray); +end + +%%%%%%%%%%%%%%%%%% +function engine = incorporate_singleconts_evidence(engine, node, evidence) +%incorporate_singleconts_evidence incorporate evidence of 1 continuous node +B = engine.cliques_bitv; +clqs_containnode = find(all(B(:,node), 2)); % all selected columns must be 1 +% Every continuous node necessarily apears as head in exactly one clique, +% which is the clique where it appears closest to the strong root. In all other +% clique potentials where it appears, it must be a tail node. +clq_ev_as_head = []; +for i = clqs_containnode(:)' + pot = struct(engine.clpot{i}); + if myismember(node, pot.cheaddom) + clq_ev_as_head = [clq_ev_as_head i]; + break; + end +end + +% If we will incorporate the evidence node which is head of a potential we must rearrange +% the juntion tree by push operation until the tail of the include potential is empty +if ~isempty(clq_ev_as_head) + assert(1 == length(clq_ev_as_head)); + i = clq_ev_as_head; + pot = struct(engine.clpot{i}); + while ~isempty(pot.ctaildom) + [engine, clqtoroot] = push(engine, i, node); + i = clqtoroot; + pot = struct(engine.clpot{i}); + end + B = engine.cliques_bitv; + clqs_containnode = find(all(B(:,node), 2)); +end + +for i = clqs_containnode(:)' + pot = struct(engine.clpot{i}); + if myismember(node, pot.cheaddom) + engine.clpot{i} = incoporate_evidence_headnode(engine.clpot{i}, node, evidence); + else + %assert(myismember(node, pot.ctaildom)); + engine.clpot{i} = incoporate_evidence_tailnode(engine.clpot{i}, node, evidence); + end +end + +%%%%%%%%%%%%%%%%%% +function newscgpot = incoporate_evidence_tailnode(pot, node, evidence) +%ENTER_EVIDENCE_TAILNODE enter the evidence of 1 tailnode of the scgpot +newscgpot = pot; +pot = struct(pot); +%if isempty(pot.ctaildom) +if ~myismember(node, pot.ctaildom) + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % In this case there is no real dependency of the head nodes % + % on the tail. The potential should be returned unchanged % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + return; +end +%newscgpot = scgpot([], [], [], []); +assert(myismember(node, pot.ctaildom)); +ni = block(find_equiv_posns(node, pot.ctaildom), pot.ctailsizes); + +ctaildom = mysetdiff(pot.ctaildom, node); +cheaddom = pot.cheaddom; +ddom = pot.ddom; +domain = mysetdiff(pot.domain, node); +dsize = pot.dsize; +ns = zeros(1, max(pot.domain)); +ns(pot.ddom) = pot.dsizes; +ns(pot.cheaddom) = pot.cheadsizes; +ns(pot.ctaildom) = pot.ctailsizes; +cheadsizes = pot.cheadsizes; +cheadsize = pot.cheadsize; +ctailsizes = ns(ctaildom); +ctailsize = sum(ns(ctaildom)); + +potarray = cell(1, dsize); +for i=1:dsize + potc = struct(pot.scgpotc{i}); + B = potc.B; + A = potc.A + B(:, ni)*evidence{node}; + B(:, ni) = []; + potarray{i} = scgcpot(cheadsize, ctailsize, potc.p, A, B, potc.C); +end + +newscgpot = scgpot(ddom, cheaddom, ctaildom, ns, potarray); + +%%%%%%%%%%%%%%%% +function newscgpot = incoporate_evidence_headnode(pot, node, evidence) +%ENTER_EVIDENCE_HEADNODE +pot = struct(pot); +y2 = evidence{node}; +assert(myismember(node, pot.cheaddom)); +assert(isempty(pot.ctaildom)); +ddom = pot.ddom; +cheaddom = mysetdiff(pot.cheaddom, node); +ctaildom = pot.ctaildom; +dsize = pot.dsize; +domain = mysetdiff(pot.domain, node); + +ns = zeros(1, max(pot.domain)); +ns(pot.ddom) = pot.dsizes; +ns(pot.cheaddom) = pot.cheadsizes; +ns(pot.ctaildom) = pot.ctailsizes; +ctailsizes = ns(ctaildom); +ctailsize = sum(ctailsizes); +cheadsizes = ns(cheaddom); +cheadsize = sum(cheadsizes); +onodesize = ns(node); + +p = zeros(1,dsize); +A1 = zeros(cheadsize, dsize); +A2 = zeros(onodesize, dsize); +C11 = zeros(cheadsize, cheadsize, dsize); +C12 = zeros(cheadsize, onodesize, dsize); +C21 = zeros(onodesize, cheadsize, dsize); +C22 = zeros(onodesize, onodesize, dsize); +ZM = zeros(onodesize, onodesize); + +n1i = block(find_equiv_posns(cheaddom, pot.cheaddom), pot.cheadsizes); +n2i = block(find_equiv_posns(node, pot.cheaddom), pot.cheadsizes); + +indic = 0; +for i=1:dsize + potc = struct(pot.scgpotc{i}); + p(i) = potc.p; + if ~isempty(n1i) + A1(:,i) = potc.A(n1i); + end + if ~isempty(n2i) + A2(:,i) = potc.A(n2i); + end + C11(:,:,i) = potc.C(n1i, n1i); + C12(:,:,i) = potc.C(n1i, n2i); + C21(:,:,i) = potc.C(n2i, n1i); + C22(:,:,i) = potc.C(n2i, n2i); + if isequal(0, C22(:,:,i)) & isequal(evidence{node}, A2(:, i)) + indic = i; + end +end + +np = zeros(1,dsize); +nA = zeros(cheadsize, dsize); +nC = zeros(cheadsize, cheadsize, dsize); + +if indic + np(:) = 0; + np(indic) = p(indic); + nA = A1; + nC = C11; +else + for i=1:dsize + if isequal(0, C22(:,:,i)) + p(i) = 0; + nA(:, i) = A1(:, i); + nC(:,:,i) = C11(:,:,i); + else + sq = (y2 - A2(:,i))' * inv(C22(:,:,i)) * (y2 - A2(:,i)); + ex = exp(-0.5*sq); + %np(i) = p(i) * ex / ( (2 * pi)^(-onodesize/2) * sqrt(det(C22(:,:,i))) ); + np(i) = p(i) * ex / ( (2 * pi)^(onodesize/2) * sqrt(det(C22(:,:,i))) ); + nA(:,i) = A1(:,i) + C12(:,:,i) * inv(C22(:,:,i)) * (y2 - A2(:,i)); + tmp1 = C12(:,:,i) * inv(C22(:,:,i)) * C21(:,:,i); + nC(:,:,i) = C11(:,:,i) - tmp1; + end + end +end + +scpot = cell(1, dsize); +W = zeros(cheadsize,ctailsize); +for i=1:dsize + scpot{i} = scgcpot(cheadsize, ctailsize, np(i), nA(:,i), W, nC(:,:,i)); +end +ns(node) = 0; +newscgpot = scgpot(ddom, cheaddom, ctaildom, ns, scpot); diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_difclq_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_difclq_nodes.m new file mode 100644 index 00000000..e1cad6c7 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_difclq_nodes.m @@ -0,0 +1,55 @@ +function marginal = marginal_difclq_nodes(engine, query_nodes) +% MARGINAL_DIFCLQ_NODES get the marginal distribution of nodes which is not in a single clique +% marginal = marginal_difclq_nodes(engine, query_nodes) + +keyboard +num_clique = length(engine.cliques); +B = engine.cliques_bitv; +clqs_containnodes = []; +for i=1:length(query_nodes) + node = query_nodes(i); + tnodes = find(all(B(:, node), 2)); + clqs_containnodes = myunion(clqs_containnodes, tnodes); +end +% get all cliques contains query nodes + +% get the minimal sub tree in junction which contains these cliques and the node closest to the root of jtree +[subtree, nroot_node] = min_subtree_conti_nodes(engine.jtree, engine.root, clqs_containnodes); +if ~mysubset(query_nodes, engine.cliques{nroot_node}); + % if query nodes is not all memers of the clique closest to the root clique performe push operation + engine = push_tree(engine, subtree, query_nodes, nroot_node); +end + +if ~(nroot_node == engine.root) + % if the clique closest to the root clique is not the root clique we must direct combine the + % potential with the potential stored in separator toward to root + p = parents(engine.jtree, nroot_node); + tpot = direct_combine_pots(engine.clpot{nroot_node}, engine.seppot{p, nroot_node}); +else + tpot = engine.clpot{nroot_node}; +end + +pot = marginalize_pot(tpot, query_nodes); +marginal = pot_to_marginal(pot); +marginal.T = normalise(marginal.T); + + + +function engine = push_tree(engine, tree, query_nodes, inode) +% PUSH_TREE recursive perform push opeartion on tree +% engine = push_tree(engine, tree, query_nodes, inode) + +cs = children(tree, inode); +for i = 1:length(cs) + node = cs(i); + push_tree(engine, tree, query_nodes, node); + push_dom = myintersect(engine.cliques{node}, query_nodes); + [engine, clqtoroot] = push(engine, node, push_dom); +end + + + + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..063c2439 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_nodes.m @@ -0,0 +1,77 @@ +function marginal = marginal_nodes(engine, query, add_ev) +% MARGINAL_NODES Compute the marginal on the specified query nodes (stab_cond_gauss) +% marginal = marginal_nodes(engine, query, add_ev) +% +% 'query' must be a singleton set. +% 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 +if isempty(engine.evidence) + hquery = query; +else + hquery = []; + for i = query + if isempty(engine.evidence{i}) + hquery = [hquery i]; + end + end +end + +bnet = bnet_from_engine(engine); + +nclq = length(engine.cliques); +clique = 0; +for i = 1:nclq + if mysubset(hquery, engine.cliques{i}) + pot = struct(engine.clpot{i}); + %if mysubset(hquery, pot.cheaddom) | mysubset(hquery, pot.ddom) + if mysubset(hquery, pot.domain) + clique = i; + break; + end + end +end + +if isempty(hquery) + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % If all requested variables are observed, no query is necessary % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + marginal.mu = []; + marginal.Sigma = []; + marginal.T = 1.0; + marginal.domain = query; +else + if clique == 0 + marginal = marginal_difclq_nodes(engine, hquery); + else + marginal = marginal_singleclq_nodes(engine, clique, hquery); + end + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Change the format of output, so that it is identical to the % + % format obtained by the same request for the junction-tree % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + marginal.domain = query; + bnet = bnet_from_engine(engine); + dquery = myintersect(bnet.dnodes,hquery); + ns = bnet.node_sizes(dquery); + if length(ns) == 0 + marginal.T = 1; + else + if length(ns) == 1 + ns = [1 ns]; + end + marginal.T = reshape(marginal.T,ns); + end +end +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/@stab_cond_gauss_inf_engine/marginal_singleclq_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_singleclq_nodes.m new file mode 100644 index 00000000..d755617f --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_singleclq_nodes.m @@ -0,0 +1,30 @@ +function marginal = marginal_singleclq_nodes(engine, i, query) +% MARGINAL_SINGLECLQ_NODES get the marginal distribution of nodes which is in a single clique +% marginal = marginal_singleclq_nodes(engine, i, query) + +pot = struct(engine.clpot{i}); +if isempty(pot.ctaildom) + if i ~= engine.root + p = parents(engine.jtree, i); + tpot = direct_combine_pots(engine.clpot{i}, engine.seppot{p, i}); + else + tpot = engine.clpot{i}; + end + pot = marginalize_pot(tpot, query); + + marginal = pot_to_marginal(pot); + marginal.T = normalise(marginal.T); +else + [engine, clqtoroot] = push(engine, i, query); + if clqtoroot == engine.root + tpot = engine.clpot{clqtoroot}; + else + p = parents(engine.jtree, clqtoroot); + tpot = direct_combine_pots(engine.clpot{clqtoroot}, engine.seppot{p, clqtoroot}); + end + pot = marginalize_pot(tpot, query); + + marginal = pot_to_marginal(pot); + marginal.T = normalise(marginal.T); +end + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/problems.txt b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/problems.txt new file mode 100644 index 00000000..fa7c6be8 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/problems.txt @@ -0,0 +1,76 @@ +PROBLEMS WITH STAB_COND_GAUSS_INF_ENGINE + + +- enter_evidence always returns ll=0 + (I set ll=0 since it is not computed) + +- fails on scg_3node, probably because the engine needs to be +re-initialized every time before enter_evidence is called, not just +when the engine is constructed. + +??? Error using ==> assert +assertion violated: + +K>> dbstack +dbstack +> In /home/eecs/murphyk/matlab/BNT/HMM/assert.m at line 9 + In /home/eecs/murphyk/matlab/BNT/examples/static/SCG/scg_3node.m at line 45 + + + +- crashes on scg3 + +Error in ==> /home/eecs/murphyk/matlab/BNT/inference/static/@stab_cond_gauss_inf_engine/stab_cond_gauss_inf_engine.m +On line 77 ==> clpot{cindex} = direct_combine_pots(pot{n}, clpot{cindex}); + +K>> dbstack +dbstack +> In /home/eecs/murphyk/matlab/BNT/inference/static/@stab_cond_gauss_inf_engine/stab_cond_gauss_inf_engine.m at line 77 + In /home/eecs/murphyk/matlab/BNT/examples/static/SCG/scg3.m at line 41 +K>> + + + + + +- fails on scg1 and scg2 + +Warning: One or more output arguments not assigned during call to 'min_subtree_conti_nodes (nearsest_node2)'. +Warning in ==> /home/eecs/murphyk/matlab/BNT/graph/min_subtree_conti_nodes.m (nearsest_node2) +On line 60 ==> nea_node = nearsest_node2(tree, nodes, n); + +K>> dbstack +dbstack +> In /home/eecs/murphyk/matlab/BNT/graph/min_subtree_conti_nodes.m (nearsest_node2) at line 60 + In /home/eecs/murphyk/matlab/BNT/graph/min_subtree_conti_nodes.m (nearest_node) at line 50 + In /home/eecs/murphyk/matlab/BNT/graph/min_subtree_conti_nodes.m at line 11 + In /home/eecs/murphyk/matlab/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_difclq_nodes.m at line 17 + In /home/eecs/murphyk/matlab/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_nodes.m at line 23 + In /home/eecs/murphyk/matlab/BNT/examples/static/SCG/scg1.m at line 42 + + + + + +- This code fragment, from BNT/graph/min_subtree_conti_nodes, is clearly redundant + +function nea_node = nearest_node(tree, root, nodes) +%get the nearest node to the root in the tree +nea_node = nearsest_node2(tree, nodes, root); + +function nea_node = nearsest_node2(tree, nodes, inode) +if myismember(inode, nodes) + nea_node = inode; + return; +end +cs = children(tree, inode); +for i = 1:length(cs) + n = cs(i); + nea_node = nearsest_node2(tree, nodes, n); +end + + +- Some names are badly chosen. 'nearsest' is a mis-spelling. 'min_subtree_conti_nodes' should be +'min_subtree_containing_nodes' or 'min_subtree_con_nodes'. + +- In general, the code needs some heavy polishing. diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/push.m b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/push.m new file mode 100644 index 00000000..193bf722 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/push.m @@ -0,0 +1,38 @@ +function [engine, clqtoroot] = push(engine, clq, pushdom) +%PUSH_POT push the variables in putshdom which is subset of clq to the clique toword the root and get new engine +%pushdom is pushed variables set +%clq is the index of the clique that pushdom belongs to + +clqdom = engine.cliques{clq}; +assert( mysubset(pushdom, clqdom)); +clqtoroot = parents(engine.jtree, clq); +%sepdom = engine.separator{clq, clqtoroot}; +sepdom = engine.separator{clqtoroot, clq}; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Calculate the strong marginal of the union of pushdom and and the separatordomain and % +% the corresponding complement % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%[margpot, comppot] = complement_pot(engine.clpot{clq}, pushdom); +newsepdom = myunion(pushdom,sepdom); +[margpot,comppot] = complement_pot(engine.clpot{clq}, newsepdom); +engine.clpot{clqtoroot} = direct_combine_pots(engine.clpot{clqtoroot}, margpot); +engine.clpot{clq} = comppot; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Calculation of the new separator and separatorpotential of the junction tree % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +engine.seppot{clqtoroot, clq} = direct_combine_pots(engine.seppot{clqtoroot, clq}, margpot); +engine.separator{clqtoroot, clq} = myunion(engine.separator{clqtoroot, clq}, pushdom); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Add pushdomain to the clique towards the root % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +engine.cliques{clqtoroot} = myunion(engine.cliques{clqtoroot}, pushdom); + +num_cliques = length(engine.cliques); +B = sparse(num_cliques, 1); +for i=1:num_cliques + B(i, engine.cliques{i}) = 1; +end +engine.cliques_bitv = B; diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/push_pot_toclique.m b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/push_pot_toclique.m new file mode 100644 index 00000000..4bcd0ed0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/push_pot_toclique.m @@ -0,0 +1,7 @@ +function engine = push_pot_toclique(engine, clqtarget, clq, nodes) +% PUSH_POT push the variables in putshdom which is subset of clq to the target clique toword the root and get new engine +% engine = push_pot_toclique(engine, clqtarget, clq, nodes) +[engine, clqtoroot] = push_pot(engine, clq, nodes) +while clqtoroot ~= clqtarget + [engine, clqtoroot] = push_pot(engine, clqtoroot, nodes) +end \ No newline at end of file diff --git a/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/stab_cond_gauss_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/stab_cond_gauss_inf_engine.m new file mode 100644 index 00000000..42c47c6a --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@stab_cond_gauss_inf_engine/stab_cond_gauss_inf_engine.m @@ -0,0 +1,178 @@ +function engine = stab_cond_gauss_inf_engine(bnet) +% STAB_COND_GAUSS_INF_ENGINE Junction tree using stable CG potentials +% engine = cond_gauss_inf_engine(bnet) +% +% This class was written by Shan Huang (shan.huang@intel.com) 2001 +% and fixed by Rainer Deventer deventer@informatik.uni-erlangen.de March 2003 +N = length(bnet.dag); +clusters = {}; +root = N; +stages = { 1:N }; +onodes = []; +engine = init_fields; +engine.evidence = []; +engine = class(engine, 'stab_cond_gauss_inf_engine', inf_engine(bnet)); + +ns = bnet.node_sizes(:); +ns(onodes) = 1; % observed nodes have only 1 possible value + +%[engine.jtree, dummy, engine.cliques, B, w, elim_order, moral_edges, fill_in_edges, strong] = ... +% dag_to_jtree(bnet, onodes, stages, clusters); + + +partial_order = determine_elim_constraints(bnet, onodes); +strong = ~isempty(partial_order); +stages = {}; +clusters = {}; +[engine.jtree, dummy_root, engine.cliques, B, w, elim_order] = + graph_to_jtree(moralize(bnet.dag), ns, partial_order, stages, clusters); + + +engine.cliques_bitv = B; +engine.clique_weight = w; +C = length(engine.cliques); +engine.clpot = cell(1,C); + +% 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); +num_cliques = length(engine.cliques); +for i=1:N + 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 + +% Compute the separators between connected cliques. +[is,js] = find(engine.jtree > 0); +engine.separator = cell(num_cliques, num_cliques); +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 +%keyboard; +engine.seppot = cell(C,C); + +pot_type = 'scg'; +check_for_cd_arcs([], bnet.cnodes, bnet.dag); + +% Make the jtree rooted, so there is a fixed message passing order. +if strong + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % Start the search for the strong root at the clique with the % + % highest number. % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + root = length(engine.cliques); + root_found = 0; + + while ((~root_found) & (root >= 1)) + root_found = test_strong_root(engine.jtree,engine.cliques,bnet.dnodes,root); + if ~root_found + root = root - 1; + end + end + assert(root > 0) + engine.root = root; + % the last clique is guaranteed to be a strong root + %engine.root = length(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_containing_nodes(engine, root); + if engine.root <= 0 + error(['no clique contains ' num2str(root)]); + end +end + +[engine.jtree, engine.preorder, engine.postorder] = mk_rooted_tree(engine.jtree, engine.root); + +% Evaluate CPDs with evidence, and convert to potentials +pot = cell(1, N); +inited = zeros(1, C); +clpot = cell(1, C); +evidence = cell(1, N); +for n=1:N + fam = family(bnet.dag, n); + e = bnet.equiv_class(n); + %pot{n} = CPD_to_scgpot(bnet.CPD{e}, fam, ns, bnet.cnodes, evidence); + pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence); + cindex = engine.clq_ass_to_node(n); + if inited(cindex) + clpot{cindex} = direct_combine_pots(pot{n}, clpot{cindex}); + else + clpot{cindex} = pot{n}; + inited(cindex) = 1; + end +end + +for i=1:C + if inited(i) == 0 + clpot{i} = scgpot([], [], [], []); + end +end + +seppot = cell(C, C); +% separators are is not need to initialize + +% collect to root (node to parents) +% Unlike the HUGIN architecture the complements are stored in the cliques during COLLECT +% and the separators are not playing a specific role during this process +for n=engine.postorder(1:end-1) + for p=parents(engine.jtree, n) + if ~isempty(engine.separator{p,n}) + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + % The empty case might happen for unlinked nodes, i.e. the DAG is not % + % a single tree, but a forest % + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + [margpot, comppot] = complement_pot(clpot{n}, engine.separator{p,n}); + clpot{n} = comppot; + clpot{p} = combine_pots(clpot{p}, margpot); + end + end +end + +% distribute message from root +% We have not to store the weak clique marginals and keep the original complement potentials. +% This is a minor variation of HUGIN architecture. +temppot = clpot; +for n=engine.preorder + for c=children(engine.jtree, n) + seppot{n,c} = marginalize_pot(temppot{n}, engine.separator{n,c}); + temppot{c} = direct_combine_pots(temppot{c}, seppot{n,c}); + end +end + +engine.clpot = clpot; +engine.seppot = seppot; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% init_fields() % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +function engine = init_fields() + +engine.evidence = []; +engine.jtree = []; +engine.cliques = []; +engine.cliques_bitv = []; +engine.clique_weight = []; +engine.preorder = []; +engine.postorder = []; +engine.root = []; +engine.clq_ass_to_node = []; +engine.separator = []; +engine.clpot =[]; +engine.seppot = []; + + + + + + + + + + + + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/CVS/Entries new file mode 100644 index 00000000..0cfdeafe --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/CVS/Entries @@ -0,0 +1,5 @@ +/enter_evidence.m/1.1.1.1/Wed Jun 19 22:05:04 2002// +/find_mpe.m/1.1.1.1/Wed Jun 19 22:11:42 2002// +/marginal_nodes.m/1.1.1.1/Thu Sep 30 03:09:00 2004// +/var_elim_inf_engine.m/1.1.1.1/Wed Jun 19 22:04:50 2002// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/CVS/Repository new file mode 100644 index 00000000..8595410d --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static/@var_elim_inf_engine diff --git a/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/enter_evidence.m b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/enter_evidence.m new file mode 100644 index 00000000..ed3fbe19 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/enter_evidence.m @@ -0,0 +1,12 @@ +function [engine, loglik] = enter_evidence(engine, evidence, varargin) +% ENTER_EVIDENCE Add the specified evidence to the network (var_elim) +% [engine, loglik] = enter_evidence(engine, evidence, ...) +% +% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector) + +% we could pre-process the evidence here, to prevent repeated work, but we don't. +engine.evidence = evidence; + +if nargout == 2 + [m, loglik] = marginal_nodes(engine, [1]); +end diff --git a/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/find_mpe.m b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/find_mpe.m new file mode 100644 index 00000000..63be5625 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/find_mpe.m @@ -0,0 +1,163 @@ +function mpe = find_mpe(engine, new_evidence, max_over) +% FIND_MPE Find the most probable explanation of the data (assignment to the hidden nodes) +% function mpe = find_mpe(engine, evidence, order) +% +% PURPOSE: +% CALC_MPE Computes the most probable explanation to the network nodes +% given the evidence. +% +% [mpe, ll] = calc_mpe(engine, new_evidence, max_over) +% +% INPUT: +% bnet - the bayesian network +% new_evidence - optional, if specified - evidence to be incorporated [cell(1,n)] +% max_over - optional, if specified determines the variable elimination order [1:n] +% +% OUTPUT: +% mpe - the MPE assignmet for the net variables (or [] if no satisfying assignment) +% ll - log assignment probability. +% +% Notes: +% 1. Adapted from '@var_elim_inf_engine\marginal_nodes' for MPE by Ron Zohar, 8/7/01 +% 2. Only discrete potentials are supported at this time. +% 3. Complexity: O(nw*) where n is the number of nodes and w* is the induced tree width. +% 4. Implementation based on: +% - R. Dechter, "Bucket Elimination: A Unifying Framework for Probabilistic Inference", +% UA1 96, pp. 211-219. + +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes; +n = length(bnet.dag); +evidence = cell(1,n); +if (nargin<2) + new_evidence = evidence; +end + +onodes = find(~isemptycell(new_evidence)); % observed nodes +hnodes = find(isemptycell(new_evidence)); % hidden nodes +pot_type = determine_pot_type(bnet, onodes); + +if pot_type ~= 'd' + error('only disrete potentials supported at this time') +end + +for i=1:n + fam = family(bnet.dag, i); + CPT{i} = convert_to_pot(bnet.CPD{bnet.equiv_class(i)}, pot_type, fam(:), evidence); +end + +% handle observed nodes: set impossible cases' probability to zero +% rather than prun matrix (this makes backtracking easier) + +for ii=onodes + lIdx = 1:ns(ii); + lIdx = setdiff(lIdx, new_evidence{ii}); + + sCPT=struct(CPT{ii}); % violate object privacy + + sargs = ''; + for jj=1:(length(sCPT.domain)-1) + sargs = [sargs, ':,']; + end + for jj=lIdx + eval(['sCPT.T(', sargs, num2str(jj), ')=0;']); + end + CPT{ii}=dpot(sCPT.domain, sCPT.sizes, sCPT.T); +end + +B = cell(1,n); +for b=1:n + B{b} = mk_initial_pot(pot_type, [], [], [], []); +end + +if (nargin<3) + max_over = (1:n); +end +order = max_over; % no attempt to optimize this + + +% Initialize the buckets with the CPDs assigned to them +for i=1:n + b = bucket_num(domain_pot(CPT{i}), order); + B{b} = multiply_pots(B{b}, CPT{i}); +end + +% Do backward phase +max_over = max_over(length(max_over):-1:1); % reverse +maximize = 1; +for i=max_over(1:end-1) + % max-ing over variable i which occurs in bucket j + j = bucket_num(i, order); + rest = mysetdiff(domain_pot(B{j}), i); + %temp = marginalize_pot_max(B{j}, rest); + temp = marginalize_pot(B{j}, rest, maximize); + b = bucket_num(domain_pot(temp), order); + % fprintf('maxing over bucket %d (var %d), putting result into bucket %d\n', j, i, b); + sB=struct(B{b}); % violate object privacy + if ~isempty(sB.domain) + B{b} = multiply_pots(B{b}, temp); + else + B{b} = temp; + end +end +result = B{1}; +marginal = pot_to_marginal(result); +[prob, mpe] = max(marginal.T); + +% handle impossible cases +if ~(prob>0) + mpe = []; + ll = -inf; + %warning('evidence has zero probability') + return +end + +ll = log(prob); + +% Do forward phase +for ii=2:n + marginal = pot_to_marginal(B{ii}); + mpeidx = []; + for jj=order(1:length(mpe)) + %assert(ismember(jj, marginal.domain)) %%% bug + temp = find_equiv_posns(jj, marginal.domain); + mpeidx = [mpeidx, temp] ; + if isempty(temp) + mpeidx = [mpeidx, Inf] ; + end + end + [mpeidxsorted sortedtompe] = sort(mpeidx) ; + + % maximize the matrix obtained from assigning values from previous buckets. + % this is done by building a string and using eval. + + kk=1; + sargs = '('; + for jj=1:length(marginal.domain) + if (jj~=1) + sargs = [sargs, ',']; + end + if (mpeidxsorted(kk)==jj) + sargs = [sargs, num2str(mpe(sortedtompe(kk)))]; + if (kk<length(mpe)) + kk = kk+1 ; + end + else + sargs = [sargs, ':']; + end + end + sargs = [sargs, ')'] ; + eval(['[val, loc] = max(marginal.T', sargs, ');']) + mpe = [mpe loc]; +end +[I,J] = sort(order); +mpe = mpe(J); + +mpe = num2cell(mpe); + +%%%%%%%%% + +function b = bucket_num(domain, order) + +b = max(find_equiv_posns(domain, order)); + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/marginal_nodes.m b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/marginal_nodes.m new file mode 100644 index 00000000..98551cb0 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/marginal_nodes.m @@ -0,0 +1,79 @@ +function [marginal, loglik] = marginal_nodes(engine, query, add_ev) +% MARGINAL_NODES Compute the marginal on the specified query nodes (var_elim) +% [marginal, loglik] = marginal_nodes(engine, query) + +if nargin < 3, add_ev = 0; end + +assert(length(query)>=1); + +evidence = engine.evidence; + +bnet = bnet_from_engine(engine); +ns = bnet.node_sizes; +n = length(bnet.dag); + +onodes = find(~isemptycell(evidence)); +hnodes = find(isemptycell(evidence)); +pot_type = determine_pot_type(bnet, onodes); + +% Fold the evidence into the CPTs - this could be done in 'enter_evidence' +CPT = cell(1,n); +for i=1:n + fam = family(bnet.dag, i); + CPT{i} = convert_to_pot(bnet.CPD{bnet.equiv_class(i)}, pot_type, fam(:), evidence); +end + + + +sum_over = mysetdiff(1:n, query); +order = [query sum_over]; % no attempt to optimize this + +% Initialize the buckets with the product of the CPTs assigned to them +B = cell(1,n+1); +for b=1:n+1 + B{b} = mk_initial_pot(pot_type, [], [], [], []); +end +for i=1:n + b = bucket_num(domain_pot(CPT{i}), order); + B{b} = multiply_pots(B{b}, CPT{i}); +end + +% Do the marginalization +sum_over = sum_over(length(sum_over):-1:1); % reverse +for i=sum_over(:)' + % summing over variable i which occurs in bucket j + j = bucket_num(i, order); + rest = mysetdiff(domain_pot(B{j}), i); + % minka + if ~isempty(rest) + temp = marginalize_pot(B{j}, rest); + b = bucket_num(domain_pot(temp), order); + %fprintf('summing over bucket %d (var %d), putting result into bucket %d\n', j, i, b); + B{b} = multiply_pots(B{b}, temp); + end +end + +% Combine all the remaining buckets into one +result = B{1}; +for i=2:length(query) + if ~isempty(domain_pot(B{i})) + result = multiply_pots(result, B{i}); + end +end +[result, loglik] = normalize_pot(result); + + +marginal = pot_to_marginal(result); +% minka: from jtree_inf_engine +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 + +%%%%%%%%% + +function b = bucket_num(domain, order) + +b = max(find_equiv_posns(domain, order)); + diff --git a/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/var_elim_inf_engine.m b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/var_elim_inf_engine.m new file mode 100644 index 00000000..dd3c940a --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/@var_elim_inf_engine/var_elim_inf_engine.m @@ -0,0 +1,15 @@ +function engine = var_elim_inf_engine(bnet, varargin) +% VAR_ELIM_INF_ENGINE Variable elimination inference engine +% engine = var_elim_inf_engine(bnet) +% +% For details on variable elimination, see +% - R. Dechter, "Bucket Elimination: A Unifying Framework for Probabilistic Inference", UA1 96, pp. 211-219. +% - Z. Li and B. D'Ambrosio, "Efficient inference in Bayes networks as a combinatorial +% optimization problem", Intl. J. Approximate Reasoning, 11(1):55-81, 1994 +% - R. McEliece and S. M. Aji, "The Generalized Distributive Law", IEEE Trans. Inform. Theory, 46(2), 2000 + + +% This is where we will store the results between enter_evidence and marginal_nodes +engine.evidence = []; + +engine = class(engine, 'var_elim_inf_engine', inf_engine(bnet)); diff --git a/sourcecodes/bnt-master/BNT/inference/static/CVS/Entries b/sourcecodes/bnt-master/BNT/inference/static/CVS/Entries new file mode 100644 index 00000000..2108bb8c --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/CVS/Entries @@ -0,0 +1,2 @@ +/dummy/1.1.1.1/Sat Jan 18 22:22:46 2003// +D diff --git a/sourcecodes/bnt-master/BNT/inference/static/CVS/Entries.Log b/sourcecodes/bnt-master/BNT/inference/static/CVS/Entries.Log new file mode 100644 index 00000000..844f5ce7 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/CVS/Entries.Log @@ -0,0 +1,17 @@ +A D/@belprop_fg_inf_engine//// +A D/@belprop_inf_engine//// +A D/@belprop_mrf2_inf_engine//// +A D/@cond_gauss_inf_engine//// +A D/@enumerative_inf_engine//// +A D/@gaussian_inf_engine//// +A D/@gibbs_sampling_inf_engine//// +A D/@global_joint_inf_engine//// +A D/@jtree_inf_engine//// +A D/@jtree_limid_inf_engine//// +A D/@jtree_mnet_inf_engine//// +A D/@jtree_sparse_inf_engine//// +A D/@likelihood_weighting_inf_engine//// +A D/@pearl_inf_engine//// +A D/@quickscore_inf_engine//// +A D/@stab_cond_gauss_inf_engine//// +A D/@var_elim_inf_engine//// diff --git a/sourcecodes/bnt-master/BNT/inference/static/CVS/Repository b/sourcecodes/bnt-master/BNT/inference/static/CVS/Repository new file mode 100644 index 00000000..347cab89 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/CVS/Repository @@ -0,0 +1 @@ +FullBNT/BNT/inference/static diff --git a/sourcecodes/bnt-master/BNT/inference/static/CVS/Root b/sourcecodes/bnt-master/BNT/inference/static/CVS/Root new file mode 100644 index 00000000..f3bd14a6 --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/CVS/Root @@ -0,0 +1 @@ +:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt diff --git a/sourcecodes/bnt-master/BNT/inference/static/dummy b/sourcecodes/bnt-master/BNT/inference/static/dummy new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/sourcecodes/bnt-master/BNT/inference/static/dummy |
