diff options
| author | ziejd2 | 2017-09-28 15:04:40 -0500 |
|---|---|---|
| committer | ziejd2 | 2017-09-28 15:04:40 -0500 |
| commit | 8070dc963753142bb86c4ed698d91fd623ed28e7 (patch) | |
| tree | d0f6dd8fc46a49b819aa55c1a90faa14d8448883 /sourcecodes/bnt-master/BNT/inference/static | |
| parent | 7cc31810d53176e805532b2789955f4eedbce6bb (diff) | |
| download | BNW-8070dc963753142bb86c4ed698d91fd623ed28e7.tar.gz | |
BNW using Octave instead of Matlab.
This version of BNW should perform the same as the original version. The only difference is that it uses Octave instead of Matlab when running BayesNet Toolbox during parameter learning. I am calling this BNW_1.02. It can be accessed at: compbio.uthsc.edu/BNW_1.02
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 |
