function L = logprob(C,Y,N,H,V,P)
% LOGPROB Log probability of data and labeling for a GCRF
%
% L = LOGPROB(C,Y,N,H,V) where C is the gcrf, Y is a labeling, N is
% the node data matrix, H is the horizontal edge data matrix, and V
% is the vertical edge data matrix. If Y contains any NaN values,
% they are interpeted as unobserved variables, and the marginal
% probability is calculated.

% GCRF.LOGPROB


% Jerod Weinman
% jerod@acm.org
    
% $Id: logprob.m 1 2009-05-07 13:41:00Z weinman $
 
% Jerod Weinman
% jerod@acm.org
% Copyright 2004, 2008, 2009
 
%    This file is part of Matlab GridCRF.
%
%    Matlab GridCRF 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.
%
%    Matlab GridCRF 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 Matlab GridCRF.  If not, see <http://www.gnu.org/licenses/>.
    
  ny = isnan(Y);
  
  if nargin<6
    P = 0;
  end;
  
  if any(ny) & P %%%% PARTIAL GRID %%%% 
    
    
    M = unrollsubgm(C,N,H,V, find(~ny));
    
    [Bn,Be,flag] = asyncbp(M.adjmat, M.nodeEnergies, M.edgeEnergies,0,[],1);
  
    L = logprob(M.adjmat, Y(~ny)', Bn, Be,1);
  else %%%% FULL OR UNOBSERVED LABELS %%%%
    
    % Pick an arbitrary labeling for any unlabeled nodes
    yw = Y(:)';
    yw(ny) = randint(C.numLabels,sum(ny),1)+1;
	
    %%%% COMPLETELY UNOBSERVED INFERENCE %%%%
	
    % Model where all label variables are unobserved
    M0 = unrollgm(C,N,H,V);
	
    [Bn0,Be0,flag0] = asyncbp(M0.adjmat, M0.nodeEnergies, M0.edgeEnergies,0,[],1);
    
    % log p(yw|x)
    L0 = logprob(M0.adjmat, yw, Bn0, Be0,1);
    
    if any(ny)
      
      %%%% PARTIALLY OBSERVED INFERENCE %%%%
      
      K = nodenum(gridsize(N,H));
      
      % Model where labeled variables are observed
      M1 = addevidence(M0,K(~ny),Y(~ny));
      
      
      [Bn1,Be1,flag] = asyncbp(M1.adjmat, M1.nodeEnergies, M1.edgeEnergies,0, [],1);
      
      % log p(w|yx)
      L1 = logprob(M1.adjmat, yw ,Bn1,Be1,1);
    else
      % Everything is observed: log 1 = 0;
      
      L1 = 0;
      
    end;
    

    L = L0 - L1;
    
  end;
