function equiv_class = mk_equiv_classes_for_dbn(inter, intra, intra1)
% MK_EQUIV_CLASSES_FOR_DBN Assign equivalent nodes to the same class for the purposes of parameter tieing.
% equiv_class = mk_equiv_classes_for_dbn(inter, intra, intra1)
%
% Each node in the first slice, and each persistent node in the 2nd slice, gets its own class.
% In addition, non-persistent nodes in slice 2 with a different set of parents than their
% counterparts in slice 1 get assigned their own class.
% (A node is persistent if it has children in the following slice.)
%
% e.g., for the following HMM-like topology
%
% X1 -> X2 -> ...
% |     |
% Y1    Y2
%
% the equivalence classes are {X1}, {Y1, Y2, ...}, {X2, X3, ...}
% which we represent as equiv_class = [1 2 3 2]. This means node 1 (X1) belongs to class 1,
% node 2 (Y1) to class 2, node 3 (X2) to class 3, and node 4 (Y2) to class 2.
% If we unroll the network for T slices, equiv_class = [1 2 3 2 3 2 ...], etc.
% This means that, during learning, the sensor model gets T samples, the transition model gets
% T-1 samples, and the prior model gets 1 sample per sequence.
%
% e.g, for the following topology
%
% A1 -> A2
% B1 -> B2
% |  \  |
% Y1   Y2
% 
% the equivalence classes are {A1}, {B1}, {Y1}, {A2, A3, ...}, {B2, B3, ...}, {Y2, Y3, ....}
% since although Y2 is non-persistent, its parents are different than Y1's.

if nargin < 3, intra1 = intra; end

ss = length(inter); % slice size
slice1_special = ~isequal(intra, intra1);
equiv_class_slice1 = 1:ss;
if slice1_special
  equiv_class_slice2 = ss+1:ss+ss;
else
  c = ss + 1; % indexes the new equivalence classes
  for i=1:ss
    if ~persistent_node(inter, i)
      equiv_class_slice2(i) = i; % slice 1 node i
    else
      equiv_class_slice2(i) = c;
      c = c + 1;
    end
  end
end
equiv_class = [equiv_class_slice1(:) equiv_class_slice2(:)];

%%%%%

function p = persistent_node(inter, i)
%
% A node is persistent if it has children in the next slice.

p = ~isempty(children(inter,i));
