function g = mixgrad(net, x, t)
%mixgrad  Evaluate the error gradient for the mixture of experts model
%
%         G = MIXGRAD(NET,X,T) takes a mixture of experts structure 
%         NET together with a matrix X of input vectors and a matrix 
%         T of target vectors, and evaluates the gradient G of the error
%         function with respect to the network weights. The error 
%         function is based on a mixture of conditional densities
%         (which can be Gaussian/Bernoulli/multinomial and leads
%         to output activation functions that are linear/logistic/softmax
%         respectively).
%
%         See also
%         mixerr, netopt, mixfwd, mixpost, mixgrad_em, mixerr_em
%
% Copyright: Perry Moerland 

% Check arguments for consistency
errstring = consist(net, 'mix', x, t);
if ~isempty(errstring)
  error(errstring);
end

nexp = net.nexp;
g = [];

[y, y_exp, y_gate] =  mixfwd(net,x);

post = mixpost(net,y_exp,y_gate,t);

for i=1:nexp
  delout = y_exp(:,:,i) - t;
  deltas_exp = diag(sparse(post(:,i)))*delout; 
  gw1  = x'*deltas_exp;
  gb1  = sum(deltas_exp,1);
  g = cat(2,g,[gw1(:)',gb1]);
end;

deltas_gate = y_gate-post;
 
% calculate gradients
gw1 = x'*deltas_gate;
gb1 =  sum(deltas_gate, 1);

g = cat(2,g,[gw1(:)', gb1]);
