function beta = back_update_belief_state(bnet, beta_tp1, scale, obs_nodes_t, vals_t, obs_nodes_tp1, vals_tp1)
% BACK_UPDATE_BELIEF_STATE Compute scaled-beta(i,t) = scale(t) * Pr(O(t+1:T) | Q(t)=i) for a DBN.
% beta = back_update_belief_state(bnet, beta_tplus1, scale, t, obs_nodes, vals)
%
% beta_tp1{c} = scaled-beta(c,t+1) where c is a cluster
% scale = Pr(O(t) | O(1:t-1)).
%
% beta{c} = scaled-beta(c,t)
% 
% The method is a generalization of the following HMM equation:
% scaled-beta(i,t) = (sum_j transmat(i,j) * obsmat(j,t+1) * scaled-beta(j,t+1)) * scale(t)

% Add evidence to slices t and t+1, and params to slice t+1
ss = bnet.slice_size;
bnet.observed_nodes = [obs_nodes_t(:)' obs_nodes_tp1(:)'+ss]; 
bnet.values(obs_nodes_tp1+ss) = vals_tp1;
bnet.values(obs_nodes_t) = vals_t;
bnet = mk_ev_specific_pot(bnet, bnet.dbn.sl2_nodes_ass_to_cl); 

% Add virtual evidence to slice t+1
cluster = bnet.dbn.cluster;
num_clusters = length(cluster);
for c=1:num_clusters
  cl = bnet.dbn.cl_con_sl2_cluster(c);
  beta_tp1{c} = set_timeslice_belief(beta_tp1{c}, 2, bnet);
  bnet.jtree.clpot{cl} = multiply_by_potential(bnet.jtree.clpot{cl}, beta_tp1{c});
end

bnet = collect_evidence(bnet);
bnet = distribute_evidence(bnet);

% Extract beta from slice t
beta = cell(1,num_clusters);
for c=1:num_clusters
  cl = bnet.dbn.cl_con_sl1_cluster(c);
  bigm = bnet.jtree.clpot{cl};
  m = marginalize_potential(bigm, cluster{c});
  %beta{c} = m;
  %beta{c} = scale_potential(beta{c}, scale);
  beta{c} = normalize_potential(m);
  % We must normalize to prevent overflow (not underflow) because we are putting 1s
  % into slice t at each step and multiplying, which causes the beta's to grow to infinity as
  % t->1. Thus we ignore the scale factors computed in the forwards pass.
end

