function L = logprob(G,Y,B,M,S)
% LOGPROB Log probability of a factor graph configuration
% 
% L = LOGPROB(G,Y) where Y is the variable assignment to the factor
% graph. L is the log probability of the configuration, found using
% LOOPYBP.
%
% L = LOGPROB(G,Y,B,M) where B and M are the factor and node
% marginals, respectively.
%
% L = LOGPROB(G,Y,B,M,S)
%
% See also LOOPYBP, SPLOOPYBP, ASYNCBP
	
% FACTORGRAPH.LOGPROB

% Jerod Weinman
% jerod@acm.org
    
% $Id: logprob.m 34 2011-07-28 17:46:52Z weinman $
 
% Jerod Weinman
% jerod@acm.org
% Copyright 2008, 2009, 2011
 
%    This file is part of MatLibFactorGraph.
%
%    MatLibFactorGraph is free software: you can redistribute it and/or modify
%    it under the terms of the GNU General Public License as published by
%    the Free Software Foundation, either version 3 of the License, or
%    (at your option) any later version.
%
%    MatLibFactorGraph is distributed in the hope that it will be useful,
%    but WITHOUT ANY WARRANTY; without even the implied warranty of
%    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%    GNU General Public License for more details.
%
%    You should have received a copy of the GNU General Public License
%    along with MatLibFactorGraph.  If not, see <http://www.gnu.org/licenses/>.

    
% See Equation (39) in
%
% JS Yedidia, WT Freeman, Y Weiss. Constructing Free Energy
% Approximations and Generalized Belief Propagation Algorithms. IEEE
% Transactions on Information Theory, 2005
  
  if nargin<4
    [B,M,flag,S] = loopybp(G);
  elseif length(B)~=length(G.factors)
    error('Length of factor marginals does not match number of factors');
  elseif length(M)~=G.numNodes
    error('Length of variable marginals does not match number of variables');
  elseif nargin==5 
    if (size(S,1)~=get(G,'numNodes') || size(S,2)~=get(G,'numFactors') )
      error('Size of messages [%d %d] does not match number of variables (%d) or factors (%d)',size(S,1),size(S,2),get(G,'numNodes'),get(G,'numFactors'));
    end;
  else
    S = {};
  end;
  
  L = 0;
  
  for f=1:length(B)
    if isempty(B{f}) 
      if ~isempty(S)
        L = L + belief(G.factors{f},S(:,f), Y(arguments(G.factors{f})));
      else
        error('Empty belief requires bp messages');
      end;
    else
      L = L + B{f}(subv2ind(size(B{f}), Y(arguments(G.factors{f}))));
    end;
  end;
  
  D = sum(adjmat(G),2);
  
  for v=1:length(M)
    L = L - (D(v)-1) * M{v}(Y(v));
  end;
