function G = factorgraph(varargin)
% FACTORGRAPH Create a factor graphical model
%
% G = FACTORGRAPH(N,F) where N is the number of variables in the
% graph and F is a list of factors on those variables.
%
% G = FACTORGRAPH Creates an empty/default grap
%
% G = FACTORGRAPH(A) where A is a factor graph returns a copy of A
  
%  Fields:
%    numNodes
%    factors
%    numLabels

% Jerod Weinman
% jerod@acm.org
    
% $Id: factorgraph.m 1 2009-05-07 13:41:00Z 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/>.

  if nargin == 0

	F = factor;
	
	% Set fields
	G.numNodes = 0;
	G.factors = F([]); % Empty factor list
	G.numLabels = [];
	
	G = class(G,'factorgraph');
	
  elseif nargin==1 & isa(varargin{1},'factorgraph')
	
	G = varargin{1};
	
  else

    N = varargin{1};
	F = varargin{2};
    
    if nargin==2 
      
      
      T = false(N,1);
      
      L = -ones(1,N);
      
      for f=1:length(F)

        %fprintf('%d ',f);
        
        A = arguments(F{f});
        
        if any(A>N)
          error('Argument to factor %d has no corresponding node',f);
        end;
        
        T(A) = 1;
        
        L1 = card(F{f});
        
        % Logical index for nodes with undetermined cardinalities
        A0 = L(A) == -1;
        
        % Assign any cardinalities yet undetermined
        L(A(A0)) = L1(A0);
        
        if any(L(A)~=L1)
          error('Node cardinality mismatch');
	  end;
	  
      end;
      
      if ~all(T)
        error('Node(s) %shas no factors',sprintf('%d ',find(~T)));
      end;
	
    elseif nargin==3
      
      % Skip check of factors
      L = varargin{3};
      
    end;
    
	G.numNodes = N;
	G.factors = F;
	G.numLabels = L;
	
	G = class(G,'factorgraph');
	
  end;
  
