about summary refs log tree commit diff
path: root/sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine
diff options
context:
space:
mode:
Diffstat (limited to 'sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine')
-rw-r--r--sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Entries7
-rw-r--r--sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Repository1
-rw-r--r--sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/CVS/Root1
-rw-r--r--sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/belprop_fg_inf_engine.m47
-rw-r--r--sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/enter_evidence.m126
-rw-r--r--sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/find_mpe.m49
-rw-r--r--sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/loopy_converged.m12
-rw-r--r--sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/marginal_nodes.m6
-rw-r--r--sourcecodes/bnt-master/BNT/inference/static/@belprop_fg_inf_engine/set_params.m24
9 files changed, 273 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