about summary refs log tree commit diff
path: root/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2
diff options
context:
space:
mode:
authorziejd22017-09-28 15:04:40 -0500
committerziejd22017-09-28 15:04:40 -0500
commit8070dc963753142bb86c4ed698d91fd623ed28e7 (patch)
treed0f6dd8fc46a49b819aa55c1a90faa14d8448883 /sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2
parent7cc31810d53176e805532b2789955f4eedbce6bb (diff)
downloadBNW-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/SLP/learning/@jtree_inf_engine2')
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/cliques_from_engine.m5
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/clq_containing_nodes.m24
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/collect_evidence.m12
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/disp.m40
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/display.m42
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/distribute_evidence.m11
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/enter_evidence.m95
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/enter_soft_evidence.m21
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/find_max_config.m35
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/find_mpe.m71
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/get.m95
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/init_pot.m20
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/jtree_inf_engine2.m239
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/marginal_family.m11
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/marginal_nodes.m22
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/set.m69
-rw-r--r--sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/set_fields.m13
17 files changed, 825 insertions, 0 deletions
diff --git a/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/cliques_from_engine.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/cliques_from_engine.m
new file mode 100644
index 00000000..cd9d871d
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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/SLP/learning/@jtree_inf_engine2/clq_containing_nodes.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/clq_containing_nodes.m
new file mode 100644
index 00000000..8904fa49
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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/SLP/learning/@jtree_inf_engine2/collect_evidence.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/collect_evidence.m
new file mode 100644
index 00000000..03c00edf
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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/SLP/learning/@jtree_inf_engine2/disp.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/disp.m
new file mode 100644
index 00000000..9fca2aaa
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/disp.m
@@ -0,0 +1,40 @@
+% ====
+% disp
+% ====
+%
+% Description :
+% -------------
+%
+% disp function for class inf_engine.
+%
+% Syntax :
+% --------
+%
+% [] = disp( obj )
+%
+% Input(s) :
+% ----------
+%
+% obj - class inf_engine
+% An instance of the class inf_engine
+%
+% Output(s) :
+% -----------
+%
+% Example(s) :
+% ------------
+%
+% disp( obj );
+%
+% Reference(s) :
+% --------------
+%
+% See also :
+% ----------
+%
+% display
+function [] = disp( obj )
+
+disp( struct( obj ) );
+    
+% End of function
diff --git a/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/display.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/display.m
new file mode 100644
index 00000000..ca40702c
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/display.m
@@ -0,0 +1,42 @@
+% =======
+% display
+% =======
+%
+% Description :
+% -------------
+%
+% display function for class inf_engine.
+%
+% Syntax :
+% --------
+%
+% [] = display( obj )
+%
+% Input(s) :
+% ----------
+%
+% obj - class inf_engine
+% An instance of the class inf_engine
+%
+% Output(s) :
+% -----------
+%
+% Example(s) :
+% ------------
+%
+% display( obj );
+%
+% Reference(s) :
+% --------------
+%
+% See also :
+% ----------
+%
+% disp
+function [] = display( obj )
+
+fprintf( '\n%s =\n\n', inputname( 1 ) ); 
+disp( struct( obj ) );
+    
+% End of function
+
diff --git a/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/distribute_evidence.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/distribute_evidence.m
new file mode 100644
index 00000000..403b8970
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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/SLP/learning/@jtree_inf_engine2/enter_evidence.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/enter_evidence.m
new file mode 100644
index 00000000..8cda6012
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/enter_evidence.m
@@ -0,0 +1,95 @@
+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);
+    % Modif RD - 2006/12/22
+    % Why end+1 it doesn't work for me...
+    % replace with n and it is ok
+    pot{ n } = dpot( n, ns( n ), soft_evidence{ n } );
+end
+% Modif RD - 2006/12/22
+% But now we have to comment this line to ensure dimension matching
+%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/SLP/learning/@jtree_inf_engine2/enter_soft_evidence.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/enter_soft_evidence.m
new file mode 100644
index 00000000..0a4346c6
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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/SLP/learning/@jtree_inf_engine2/find_max_config.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/find_max_config.m
new file mode 100644
index 00000000..5053b1e8
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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/SLP/learning/@jtree_inf_engine2/find_mpe.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/find_mpe.m
new file mode 100644
index 00000000..8a46c1ed
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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/SLP/learning/@jtree_inf_engine2/get.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/get.m
new file mode 100644
index 00000000..af4f7d88
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/get.m
@@ -0,0 +1,95 @@
+% ===
+% get
+% ===
+%
+% Description :
+% -------------
+%
+% Reading method for the class' attributes. 
+% 
+% Syntax :
+% --------
+%
+% val = get( obj, attribute_name );
+%
+% Input(s) :
+% ----------
+%
+% obj - class inf_engine
+% An instance of the class inf_engine
+%
+% attribute_name - string
+% The name of a class' attribute
+% For details about the attribute's names, see the constructor
+% (inf_engine.m)
+%
+% Output(s) :
+% -----------
+%
+% val - any
+% The value of the specified attribute
+%
+% Example(s) :
+% ------------
+%
+% val = get( obj, 'attribute_name' );
+%
+% Reference(s) :
+% --------------
+%
+% See also :
+% ----------
+%
+% inf_engine
+% set
+function [ val ] = get( engine, attribute_name )
+
+val = [];
+
+% Processing 
+val = get( engine.inf_engine, attribute_name );
+
+% Processing    
+arg = upper( attribute_name );
+
+switch arg      
+ case upper( 'evidence' )
+  val = engine.evidence;
+ case upper( 'jtree' )
+  val = engine.jtree;
+ case upper( 'cliques' )
+  val = engine.cliques;
+  case upper( 'separator' )
+  val = engine.separator;
+  case upper( 'cliques_bitv' )
+  val = engine.cliques_bitv;
+  case upper( 'clique_weight' )
+  val = engine.clique_weight;
+  case upper( 'clpot' )
+  val = engine.clpot;
+  case upper( 'clq_ass_to_node' )
+  val = engine.clq_ass_to_node;
+ case upper( 'root_clq' )
+  val = engine.root_clq;
+  case upper( 'preorder' )
+  val = engine.preorder;
+  case upper( 'postorder' )
+  val = engine.postorder;
+  case upper( 'preorder_children' )
+  val = engine.preorder_children;
+  case upper( 'postorder_parents' )
+  val = engine.postorder_parents;
+  case upper( 'maximize' )
+  val = engine.maximize;
+  case upper( 'evidence' )
+  val = engine.evidence;
+             
+ otherwise
+  %   warning_str = [ 'inf_engine - get : attribute ' ...
+  % 		  arg ' doesn''t exist' ];
+  
+  %   warning( warning_str );
+end
+
+% End of function
+
diff --git a/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/init_pot.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/init_pot.m
new file mode 100644
index 00000000..857e6266
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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/SLP/learning/@jtree_inf_engine2/jtree_inf_engine2.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/jtree_inf_engine2.m
new file mode 100644
index 00000000..594833de
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/jtree_inf_engine2.m
@@ -0,0 +1,239 @@
+function [ engine ] = jtree_inf_engine_rd( bnet, varargin )
+% JTREE_INF_ENGINE2 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.
+%
+% modification of the calculus of cliques from JTREE_INF_ENGINE
+
+
+% set default params
+N = length( bnet.dag );
+
+% Optional argument processing
+[ b_verb, clusters, root, stages ] = jtree_inf_engine2_varargin_mgt( N, varargin );
+
+% --- Verbose --- %
+if b_verb
+    fprintf( '/ ------------------------------- \\\n' );
+    fprintf( '| jtree_inf_engine2 - verbose mode |\n' );
+    time_i = datenum( clock );
+end
+% --------------- %
+
+% Initialization
+% ==============
+
+% Class initialization
+engine = init_fields;
+engine = class( engine, 'jtree_inf_engine2', inf_engine( bnet ) );
+
+% Default parameters
+maximize = 0;
+onodes = bnet.observed;
+
+% Optional parameters given by user
+% engine = set( engine, varargin{ : } );
+
+% Building of the junction tree
+% =============================
+
+% Elimination ordering
+% --------------------
+% --- Verbose --- %
+if b_verb
+    fprintf( 'Compute elimination constraints ...' );
+    time_i_cur = datenum( clock );
+end
+% --------------- %
+porder = determine_elim_constraints( bnet, onodes );
+strong = ~isempty( porder );
+% --- Verbose --- %
+if b_verb
+    time_f_cur = datenum( clock );
+    time_cur_str = datestr( time_f_cur - time_i_cur, 'HH:MM:SS' );
+    fprintf( ' [Done] - elapsed time = %s\n', time_cur_str );
+end
+% --------------- %
+
+
+% Moralization
+% ------------
+% --- Verbose --- %
+if b_verb
+    fprintf( 'Moralization ...' );
+    time_i_cur = datenum( clock );
+end
+% --------------- %
+ns = bnet.node_sizes( : );
+ns( onodes ) = 1; % observed nodes have only 1 possible value
+moral_graph = moralize( bnet.dag );
+% --- Verbose --- %
+if b_verb
+    time_f_cur = datenum( clock );
+    time_cur_str = datestr( time_f_cur - time_i_cur, 'HH:MM:SS' );
+    fprintf( ' [Done] - elapsed time = %s\n', time_cur_str );
+end
+% --------------- %
+
+
+% Junction tree building
+% ----------------------
+% --- Verbose --- %
+if b_verb
+    fprintf( 'Building the junction tree ...' );
+    time_i_cur = datenum( clock );
+end
+% --------------- %
+[ engine.jtree, root2, engine.cliques, B, w, elim_order ] = ...
+    graph_to_jtree( moral_graph, ns, porder, stages, clusters );
+% --- Verbose --- %
+if b_verb
+    time_f_cur = datenum( clock );
+    time_cur_str = datestr( time_f_cur - time_i_cur, 'HH:MM:SS' );
+    fprintf( ' [Done] - elapsed time = %s\n', time_cur_str );
+end
+% --------------- %
+
+
+engine.cliques_bitv = B;
+engine.clique_weight = w;
+C = length( engine.cliques );
+engine.clpot = cell(1,C);
+
+% Separators computation
+% ----------------------
+
+% --- Verbose --- %
+if b_verb
+    fprintf( 'Separators computation ...' );
+    time_i_cur = datenum( clock );
+end
+% --------------- %
+% 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 );
+  % intersect(cliques{i}, cliques{j});
+  engine.separator{ i, j } = find( B( i, : ) & B( j, : ) ); 
+end
+% --------------- %
+if b_verb
+    time_f_cur = datenum( clock );
+    time_cur_str = datestr( time_f_cur - time_i_cur, 'HH:MM:SS' );
+    fprintf( ' [Done] - elapsed time = %s\n', time_cur_str );
+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));
+  % all selected columns must be 1
+  clqs_containing_family = find( all( B( :, family( bnet.dag, i ) ), 2 ) );
+  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
+
+% --- Verbose --- %
+if b_verb
+    time_f = datenum( clock );
+    time_str = datestr( time_f - time_i, 'HH:MM:SS' );
+    fprintf( 'Elapsed time = %s\n', time_str' );
+    fprintf( '\\ ------------------------------- /\n' );
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function [ b_verb, clusters, root, stages ] = jtree_inf_engine2_varargin_mgt( N, parent_varargin )
+
+% Number of variable arguments
+nb_varargin = length( parent_varargin );
+
+% Default parameters
+b_verb = 0;
+clusters = {};
+root = N;
+stages = { 1:N };
+
+% Processing
+for i = 1:2:nb_varargin
+    
+    arg_i = upper( parent_varargin{ i } );
+    val_i = parent_varargin{ i + 1 };
+    
+    switch arg_i      
+     case upper( 'EngineVerbose' )
+      b_verb = val_i;
+     case upper( 'Clusters' )
+      clusters = val_i;
+     case upper( 'Root' )
+      root = val_i;
+     case upper( 'Stages' )
+      stages = val_i;
+     otherwise
+    end
+    
+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/SLP/learning/@jtree_inf_engine2/marginal_family.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/marginal_family.m
new file mode 100644
index 00000000..eff60ca2
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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/SLP/learning/@jtree_inf_engine2/marginal_nodes.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/marginal_nodes.m
new file mode 100644
index 00000000..6413172c
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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/SLP/learning/@jtree_inf_engine2/set.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/set.m
new file mode 100644
index 00000000..2ade7cb2
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/set.m
@@ -0,0 +1,69 @@
+% ===
+% set
+% ===
+%
+% Description :
+% -------------
+%
+% Writing method for the class' attributes. 
+% 
+% Syntax :
+% --------
+%
+% obj = set( obj, attrib_name_1, val_1, ..., attrib_name_n, val_n );
+%
+% Input(s) :
+% ----------
+%
+% obj - class inf_engine
+% An instance of the class inf_engine
+%
+% > Optionals : 'attrib_name'/value form
+% For details about the attribute's names, see the constructor
+% (inf_engine.m)
+%
+% Output(s) :
+% -----------
+%
+% obj - class inf_engine
+% The updated object
+%
+% Example(s) :
+% ------------
+%
+% obj = set( obj, 'attrib_1', val_1, ..., 'attrib_n', val_n );
+%
+% Reference(s) :
+% --------------
+%
+% See also :
+% ----------
+%
+% inf_engine
+% get
+function [ engine ] = set( engine, varargin )
+
+engine.inf_engine = set( engine.inf_engine, varargin{ : } );
+
+% Processing
+% Number of variable arguments
+nb_varargin = length( varargin );
+
+for i = 1:2:nb_varargin
+    
+    arg_i = upper( varargin{ i } );
+    val_i = varargin{ i + 1 };
+    
+    switch arg_i      
+     case upper( 'maximize' )
+      engine.maximize = val_i;
+     otherwise
+%       warning_str = [ 'inf_engine - set : attribute ' ...
+% 		      arg_i ' doesn''t exist' ];
+		      
+%       warning( warning_str );
+    end
+    
+end
+    
+% End of function
\ No newline at end of file
diff --git a/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/set_fields.m b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/set_fields.m
new file mode 100644
index 00000000..e75cfa45
--- /dev/null
+++ b/sourcecodes/bnt-master/SLP/learning/@jtree_inf_engine2/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