function bnet = learn_struct_dbn(bnet, ev)
% LEARN_STRUCT_DBN Find the best inter-slice matrix of a DBN.
% bnet = learn_struct_dbn(bnet, ev)
%
% ev is a single time series.
% We assume there are no intra slice connections.

num_cases = length(ev);
assert(num_cases==1);

converged = 0;
num_iter = 1;
ss = bnet.slice_size;
max_iter = 10;
prev_inter = zeros(ss);

while ~converged  & (num_iter <= max_iter) 
  fprintf(1, 'Structural iteration %d\n', num_iter); 
  num_iter = num_iter + 1;
  clear options;
  options.max_iter = 5;
  [bnet, LL] = learn_params(bnet, ev, options);
  % Form a clique containing two consecutive slices.
  % This means we must be careful not to have too many hidden variables per slice.
  [bnet, clique] = schedule_marginals(bnet, {1:(2*ss)});
  fprintf('computing ESS...');
  [bnet, ll] = enter_evidence(bnet, ev(1));
  fprintf('done\n');
  inter = zeros(ss);
  for i=1:ss
    fprintf('\nfinding best parents for node %d\n', i);
    %[ps] = find_best_parents('BIC', i, 1:ss, bnet, clique);
    [ps] = find_best_parents('MI', i, 1:ss, bnet, clique);
    inter(ps,i) = 1;
  end
  inter
  if isequal(inter, prev_inter)
    converged = 1;
  else
    prev_inter = inter;
    bnet.inter = inter;
    for i=1:ss
      ps = parents(inter, i);
      old_ps = bnet.bnodes{i+ss}.parents;
      if ~isequal(ps, old_ps)
	additions = setdiff(ps, old_ps);
	deletions = setdiff(old_ps, ps);
	if 0
	  if ~isempty(additions)
	    fprintf('additions to node %d:', i); disp(additions);
	  end
	  if ~isempty(deletions)
	    fprintf('deletions from node %d:', i); disp(deletions);
	  end
	end
	bnet.bnodes{i+ss} = modify_parents_bnode(bnet.bnodes{i+ss}, parents(inter, i), bnet);
      end
    end
    bnet = schedule_marginals(bnet, {}); % update the join tree
  end
end
