function [B,D,mu] = extract_params_from_gbn(bnet, num_nodes)
% Extract all the local parameters of each Gaussian node, and collect them into global matrices.
% [B,D,mu] = extract_params_from_gbn(bnet, num_nodes)
%
% B(i,j) is a block matrix that contains the transposed weight matrix from node i to node j.
% D(i,i) is a block matrix that contains the noise covariance matrix for node i.
% mu(i) is a block vector that contains the shifted noise mean for node i.
% i,j run from 1 .. num_nodes, which defaults to bnet.num_nodes.
%
% See "Gaussian Influence Diagrams", R. Shachter and C. R. Kenley, 1989,
% Management Science, 35(5):527--550.

% In Shachter's model, the mean of each node in the global gaussian is
% the same as the node's local unconditional mean.
% In Alag's model (which we use), the global mean gets shifted.

if nargin<2, num_nodes = length(bnet.adj_mat); end

all_nodes = 1:num_nodes;
assert(subset(all_nodes, bnet.cts_nodes));

bs = bnet.blocks(:);
num_scalar_nodes = sum(bs);

B = zeros(num_scalar_nodes, num_scalar_nodes);
D = zeros(num_scalar_nodes, num_scalar_nodes);
mu = zeros(num_scalar_nodes,1); % col vec


for i = 1:num_nodes % in topological order
  ps = parents(bnet.adj_mat, i);
  e = bnet.equiv_class(i);
  m = bnet.bnodes{e}.mean(:);
  if length(ps) == 0
    mu(block(i,bs)) = m;
  else
    mu(block(i,bs)) = m + bnet.bnodes{e}.weights *  mu(block(ps,bs));
  end
  B(block(ps,bs), block(i,bs)) = bnet.bnodes{e}.weights';
  D(block(i,bs), block(i,bs)) = bnet.bnodes{e}.cov;
end



