function [y,y_exp,y_gate] = mixfwd(net,x)
%mixfwd	Forward propagation through mixture of experts model.
%
%	Y = MIXFWD(NET, X) takes a mixtures-of-experts model data structure
%	NET together with a matrix X of input vectors, and forward propagates
%	the inputs through the network to generate a matrix Y of output
%	vectors. Each row of X corresponds to one input vector and each row
%	of Y corresponds to one output vector.
%
%       [Y,Y_EXP,Y_GATE] = MIXFWD(NET, X) also generates a 3-dimensional
%       matrix Y_EXP where each submatrix Y_EXP(:,:,i) corresponds to the
%       matrix of output vectors of expert i. Y_GATE contains the matrix
%       of output vectors of the gating network.
%
%       See also
%       mix, glmfwd
%
%       Copyright: Perry Moerland

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

ndata = size(x, 1);
nexp  = net.nexp;
nout  = net.nout;

% forward propagation for the expert networks
y_exp = zeros(ndata,nout,nexp);
for i=1:nexp
  y_exp(:,:,i) = glmfwd(net.exp(i),x);
end;

% forward propagation for the gating network
switch net.tag
  case {'kernel','ker&var'}
    y_gate = gmmpost(net.gate,x);
  case {'mfa','mfa&var'}
    y_gate = mfapost(net.gate,x);
  case {'mpca','mpca&var'}
    y_gate = mpcapost(net.gate,x);
  otherwise
    y_gate = glmfwd(net.gate,x);
end;

%  output of the mixture of experts network
y = zeros(ndata,nout);
for i=1:nexp, 
      temp = y_gate(:,i);
      y = y + diag(sparse(temp))*y_exp(:,:,i);
end;
