function [alpha, scale, post] = update_belief_state(bnet, alpha_tm1, obs_nodes_t, vals_t, obs_nodes_tm1, vals_tm1, t)
% UPDATE_BELIEF_STATE Compute scaled-alpha(:,t) = Pr(Q(t) | O(1:t)) for a DBN.
% [alpha, scale, post] = update_belief_state(bnet, alpha_tm1)
%
% alpha{c} = scaled-alpha(c,t)
% scale = Pr(O(t) | O(1:t-1))
% post{k} = potential on clique k in the jtree for slices t-1 and t
%
% The method is a generalization of the following HMM equation:
% alpha(j,t) = normalise( (sum_i alpha(i,t-1) * transmat(i,j)) * obsmat(j,t) )

ss = bnet.slice_size;

% We include the evidence for slice t and the CPTs for all the nodes in slice t.
% Later we will multiply on alpha(t-1) as a prior for t-1.
% We don't multiply in the CPTs for slice t-1, since they are already incorporated into alpha(t-1).
% We add the evidence for slice t-1, since it plus alpha_tm1 define the belief state for t-1.
% If we don't do this, the scaled posteriors will all be correct, but the scaling
% factor will not be.
% Also, observed nodes have size 1 (if discrete), so the potentials will be smaller.
% (Note that, since bnet is local to this function, changing bnet.values does not affect
% the behavior of marginal_nodes which calls add_evidence_to_marginal.)
bnet.observed_nodes = [obs_nodes_tm1(:)' obs_nodes_t(:)'+ss];
bnet.values(obs_nodes_tm1) = vals_tm1;
bnet.values(obs_nodes_t+ss) = vals_t;
bnet = mk_ev_specific_pot(bnet, bnet.dbn.sl2_nodes_ass_to_cl);

% Add alpha_tm1 to slice t-1 as a prior
cluster = bnet.dbn.cluster;
num_clusters = length(cluster);
for c=1:num_clusters
  cl = bnet.dbn.cl_con_sl1_cluster(c);
  bnet.jtree.clpot{cl} = multiply_by_potential(bnet.jtree.clpot{cl}, alpha_tm1{c});
end

bnet = collect_evidence(bnet);
bnet = distribute_evidence(bnet);
num_cliques = length(bnet.jtree.cliques);
for c=1:num_cliques
  [bnet.jtree.clpot{c}, lik] = normalize_potential(bnet.jtree.clpot{c});
end
if lik > 0
  scale = 1/lik;
else
  scale = 0;
end
%lik = lik + (lik==0)*eps;
%scale = 1/lik;

% Extract alpha from slice t
alpha = cell(1,num_clusters);
for c=1:num_clusters
  cl = bnet.dbn.cl_con_sl2_cluster(c);
  bigm = bnet.jtree.clpot{cl};
  m = marginalize_potential(bigm, cluster{c}+ss);
  alpha{c} = m;
  alpha{c}.domain = cluster{c};
  alpha{c} = set_timeslice_belief(alpha{c}, 1, bnet);
end

% Extract the filtered posterior on all the cliques
post = cell(1,num_cliques);
for c=1:num_cliques
  post{c} = bnet.jtree.clpot{c};
  post{c} = set_timeslice_belief(post{c}, t-1, bnet);
end
