ó
ú£Õ\c           @   sÎ   d  Z  d d l Z d d l Z d d l Z d j d g ƒ Z d d d d d	 g Z d	 e j f d
 „  ƒ  YZ	 d „  Z
 e j d „ Z d „  Z d „  Z d „  Z d „  Z d „  Z d e j d „ Z d „  Z d S(   sÆ   
Algorithms for chordal graphs.

A graph is chordal if every cycle of length at least 4 has a chord
(an edge joining two nodes not adjacent in the cycle).
http://en.wikipedia.org/wiki/Chordal_graph
iÿÿÿÿNs   
s'   Jesus Cerquides <cerquide@iiia.csic.es>t
   is_chordalt   find_induced_nodest   chordal_graph_cliquest   chordal_graph_treewidtht   NetworkXTreewidthBoundExceededc           B   s   e  Z d  Z RS(   sW   Exception raised when a treewidth bound has been provided and it has 
    been exceeded(   t   __name__t
   __module__t   __doc__(    (    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyR      s   c         C   s`   |  j  ƒ  r t j d ƒ ‚ n  |  j ƒ  r< t j d ƒ ‚ n  t t |  ƒ ƒ d k rX t St Sd S(   sù  Checks whether G is a chordal graph.

    A graph is chordal if every cycle of length at least 4 has a chord
    (an edge joining two nodes not adjacent in the cycle).

    Parameters
    ----------
    G : graph  
      A NetworkX graph.  

    Returns
    -------
    chordal : bool
      True if G is a chordal graph and False otherwise.
    
    Raises
    ------
    NetworkXError
        The algorithm does not support DiGraph, MultiGraph and MultiDiGraph. 
        If the input graph is an instance of one of these classes, a
        NetworkXError is raised.
        
    Examples
    --------
    >>> import networkx as nx
    >>> e=[(1,2),(1,3),(2,3),(2,4),(3,4),(3,5),(3,6),(4,5),(4,6),(5,6)]
    >>> G=nx.Graph(e)
    >>> nx.is_chordal(G)
    True
   
    Notes
    -----
    The routine tries to go through every node following maximum cardinality 
    search. It returns False when it finds that the separator for any node 
    is not a clique.  Based on the algorithms in [1]_.

    References
    ----------
    .. [1] R. E. Tarjan and M. Yannakakis, Simple linear-time algorithms 
       to test chordality of graphs, test acyclicity of hypergraphs, and 
       selectively reduce acyclic hypergraphs, SIAM J. Comput., 13 (1984), 
       pp. 566â€“579.
    s   Directed graphs not supporteds(   Multiply connected graphs not supported.i    N(   t   is_directedt   nxt   NetworkXErrort   is_multigrapht   lent   _find_chordality_breakert   Truet   False(   t   G(    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyR       s    ,c         C   s#  t  |  ƒ s t j d ƒ ‚ n  t j |  ƒ } | j | | ƒ t ƒ  } t | | | ƒ } xh | rÂ | \ } } }	 | j | ƒ x- | D]% }
 |
 | k r„ | j | |
 ƒ q„ q„ Wt | | | ƒ } q[ W| r| j | ƒ xF |  | D]7 } t	 | t |  | ƒ @ƒ d k rá | j | ƒ Pqá qá Wn  | S(   s¥  Returns the set of induced nodes in the path from s to t. 

    Parameters
    ----------
    G : graph
      A chordal NetworkX graph 
    s : node
	Source node to look for induced nodes
    t : node
	Destination node to look for induced nodes
    treewith_bound: float
        Maximum treewidth acceptable for the graph H. The search 
        for induced nodes will end as soon as the treewidth_bound is exceeded.
   
    Returns
    -------
    I : Set of nodes
	The set of induced nodes in the path from s to t in G
    
    Raises
    ------
    NetworkXError
        The algorithm does not support DiGraph, MultiGraph and MultiDiGraph. 
        If the input graph is an instance of one of these classes, a
        NetworkXError is raised.
        The algorithm can only be applied to chordal graphs. If
        the input graph is found to be non-chordal, a NetworkXError is raised.
        
    Examples
    --------
    >>> import networkx as nx
    >>> G=nx.Graph()  
    >>> G = nx.generators.classic.path_graph(10)
    >>> I = nx.find_induced_nodes(G,1,9,2)
    >>> list(I)
    [1, 2, 3, 4, 5, 6, 7, 8, 9]

    Notes
    -----
    G must be a chordal graph and (s,t) an edge that is not in G. 

    If a treewidth_bound is provided, the search for induced nodes will end 
    as soon as the treewidth_bound is exceeded.
    
    The algorithm is inspired by Algorithm 4 in [1]_.
    A formal definition of induced node can also be found on that reference.
    
    References
    ----------
    .. [1] Learning Bounded Treewidth Bayesian Networks. 
       Gal Elidan, Stephen Gould; JMLR, 9(Dec):2699--2731, 2008. 
       http://jmlr.csail.mit.edu/papers/volume9/elidan08a/elidan08a.pdf
    s   Input graph is not chordal.i   (
   R    R	   R
   t   Grapht   add_edget   setR   t   updatet   addR   (   R   t   st   tt   treewidth_boundt   Ht   It   triplett   ut   vt   wt   n(    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyR   S   s(    6		 c         C   sX   t  |  ƒ s t j d ƒ ‚ n  t ƒ  } x* t j j |  ƒ D] } | t | ƒ O} q: W| S(   sÏ  Returns the set of maximal cliques of a chordal graph.
    
    The algorithm breaks the graph in connected components and performs a 
    maximum cardinality search in each component to get the cliques.
    
    Parameters
    ----------
    G : graph
      A NetworkX graph 
    
    Returns
    -------
    cliques : A set containing the maximal cliques in G.
    
    Raises
    ------
    NetworkXError
        The algorithm does not support DiGraph, MultiGraph and MultiDiGraph. 
        If the input graph is an instance of one of these classes, a
        NetworkXError is raised.
        The algorithm can only be applied to chordal graphs. If the
        input graph is found to be non-chordal, a NetworkXError is raised.
        
    Examples
    --------
    >>> import networkx as nx
    >>> e= [(1,2),(1,3),(2,3),(2,4),(3,4),(3,5),(3,6),(4,5),(4,6),(5,6),(7,8)]
    >>> G = nx.Graph(e)
    >>> G.add_node(9)    
    >>> setlist = nx.chordal_graph_cliques(G)
    s   Input graph is not chordal.(   R    R	   R
   R   t	   connectedt   connected_component_subgraphst    _connected_chordal_graph_cliques(   R   t   cliquest   C(    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyR       s     	c         C   s[   t  |  ƒ s t j d ƒ ‚ n  d } x, t j |  ƒ D] } t | t | ƒ ƒ } q4 W| d S(   s¤  Returns the treewidth of the chordal graph G.
 
    Parameters
    ----------
    G : graph
      A NetworkX graph 
    
    Returns
    -------
    treewidth : int
	The size of the largest clique in the graph minus one.
    
    Raises
    ------
    NetworkXError
        The algorithm does not support DiGraph, MultiGraph and MultiDiGraph. 
        If the input graph is an instance of one of these classes, a
        NetworkXError is raised.
        The algorithm can only be applied to chordal graphs. If
        the input graph is found to be non-chordal, a NetworkXError is raised.
        
    Examples
    --------
    >>> import networkx as nx
    >>> e = [(1,2),(1,3),(2,3),(2,4),(3,4),(3,5),(3,6),(4,5),(4,6),(5,6),(7,8)]
    >>> G = nx.Graph(e)
    >>> G.add_node(9)    
    >>> nx.chordal_graph_treewidth(G)
    3

    References
    ----------
    .. [1] http://en.wikipedia.org/wiki/Tree_decomposition#Treewidth
    s   Input graph is not chordal.iÿÿÿÿi   (   R    R	   R
   R   t   maxR   (   R   t
   max_cliquet   clique(    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyR   Ê   s    #c         C   sh   |  j  ƒ  d k r$ t j d ƒ ‚ n  |  j ƒ  } | d k  r@ t S|  j ƒ  } | | d d } | | k S(   s&   Returns True if G is a complete graph.i    s'   Self loop found in _is_complete_graph()i   i   (   t   number_of_selfloopsR	   R
   t   number_of_nodesR   t   number_of_edges(   R   R   t   et	   max_edges(    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyt   _is_complete_graphõ   s    c         C   s^   t  |  ƒ } xK |  D]C } | t  t |  | j ƒ  ƒ | g ƒ } | r | | j ƒ  f Sq Wd S(   s6    Given a non-complete graph G, returns a missing edge.N(   R   t   listt   keyst   pop(   R   t   nodesR   t   missing(    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyt   _find_missing_edge  s
    'c         C   se   d } xX | D]P } t  g  |  | D] } | | k r! | ^ q! ƒ } | | k r | } | } q q W| S(   sa   Returns a the node in choices that has more connections in G 
    to nodes in wanna_connect.
    iÿÿÿÿ(   R   (   R   t   choicest   wanna_connectt
   max_numbert   xt   yt   numbert   max_cardinality_node(    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyt   _max_cardinality_node
  s    /c         C   s  t  |  ƒ } | d k r0 t j t | ƒ ƒ } n  | j | ƒ t  | g ƒ } d } x¾ | rt |  | | ƒ } | j | ƒ | j | ƒ t  |  | ƒ | @} |  j | ƒ } t	 | ƒ rð t
 | t | ƒ ƒ } | | k rt j d | ƒ ‚ qqU t | ƒ \ }	 }
 |	 | |
 f SqU Wd S(   s&   Given a graph G, starts a max cardinality search 
    (starting from s if s is given and from a random node otherwise)
    trying to find a non-chordal cycle. 

    If it does find one, it returns (u,v,w) where u,v,w are the three
    nodes that together with s are involved in the cycle.
    iÿÿÿÿs   treewidth_bound exceeded: %sN(    (   R   t   Nonet   randomt   choiceR.   t   removeR;   R   t   subgraphR-   R%   R   R	   R   R3   (   R   R   R   t
   unnumberedt   numberedt   current_treewidthR   t   clique_wanna_bet   sgR   R   (    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyR     s(    		c   	      C   s[  |  j  ƒ  d k r1 t |  j ƒ  ƒ } t | g ƒ St ƒ  } t |  j ƒ  ƒ } t j t | ƒ ƒ } | j | ƒ t | g ƒ } t | g ƒ } x± | r?t |  | | ƒ } | j | ƒ | j	 | ƒ t |  j
 | ƒ ƒ | @} |  j | ƒ } t | ƒ r-| j	 | ƒ | | k s$| j	 t | ƒ ƒ n  | } q t j d ƒ ‚ q W| j	 t | ƒ ƒ | Sd S(   s?   Return the set of maximal cliques of a connected chordal graph.i   s   Input graph is not chordal.N(   R)   t	   frozensetR1   R   R=   R>   R.   R?   R;   R   t	   neighborsR@   R-   R	   R
   (	   R   R7   R#   RA   R   RB   RD   t   new_clique_wanna_beRE   (    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyR"   =  s.    			(   R   t   networkxR	   R=   t   syst   joint   __authors__t   __all__t   NetworkXExceptionR   R    t   maxsizeR   R   R   R-   R3   R;   R<   R   R"   (    (    (    s_   /Users/dxp/prism/prism-games/prism-examples/smgs/car/networkx/algorithms/chordal/chordal_alg.pyt   <module>   s&   		5M	*	+				%