ó
 ,µ[c           @   sÒ   d  Z  d d l Z d d l Z d d l m 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).
https://en.wikipedia.org/wiki/Chordal_graph
iÿÿÿÿN(   t   arbitrary_elements   
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(   sV   Exception raised when a treewidth bound has been provided and it has
    been exceeded(   t   __name__t
   __module__t   __doc__(    (    (    s:   lib/python2.7/site-packages/networkx/algorithms/chordal.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
        :exc:`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:   lib/python2.7/site-packages/networkx/algorithms/chordal.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
        :exc:`NetworkXError` is raised.
        The algorithm can only be applied to chordal graphs. If
        the input graph is found to be non-chordal, a :exc:`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:   lib/python2.7/site-packages/networkx/algorithms/chordal.pyR   U   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
        :exc:`NetworkXError` is raised.
        The algorithm can only be applied to chordal graphs. If the
        input graph is found to be non-chordal, a :exc:`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:   lib/python2.7/site-packages/networkx/algorithms/chordal.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
        :exc:`NetworkXError` is raised.
        The algorithm can only be applied to chordal graphs. If
        the input graph is found to be non-chordal, a :exc:`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] https://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:   lib/python2.7/site-packages/networkx/algorithms/chordal.pyR   Í   s    #c         C   sk   t  j |  ƒ d k r' t  j d ƒ ‚ n  |  j ƒ  } | d k  rC 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   (   R
   t   number_of_selfloopsR   t   number_of_nodesR   t   number_of_edges(   R   R    t   et	   max_edges(    (    s:   lib/python2.7/site-packages/networkx/algorithms/chordal.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:   lib/python2.7/site-packages/networkx/algorithms/chordal.pyt   _find_missing_edge  s
    'c         C   se   d } xX | D]P } t  g  |  | D] } | | k r! | ^ q! ƒ } | | k r | } | } q q W| S(   s`   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:   lib/python2.7/site-packages/networkx/algorithms/chordal.pyt   _max_cardinality_node  s    /c         C   s  t  |  ƒ } | d k r' t |  ƒ } n  | j | ƒ t  | g ƒ } d } x¾ | r	t |  | | ƒ } | j | ƒ | j | ƒ t  |  | ƒ | @} |  j | ƒ } t | ƒ rç t | t	 | ƒ ƒ } | | k rt
 j d | ƒ ‚ qqL t | ƒ \ }	 }
 |	 | |
 f SqL Wd S(   s(   Given a graph G, starts a max cardinality search
    (starting from s if s is given and from an arbitrary 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   NoneR    t   removeR<   R   t   subgraphR.   R&   R   R
   R   R4   (   R   R   R   t
   unnumberedt   numberedt   current_treewidthR   t   clique_wanna_bet   sgR   R   (    (    s:   lib/python2.7/site-packages/networkx/algorithms/chordal.pyR     s(    		c   	      C   sR  |  j  ƒ  d k r1 t |  j ƒ  ƒ } t | g ƒ St ƒ  } t |  j ƒ  ƒ } t |  ƒ } | j | ƒ t | g ƒ } t | g ƒ } x± | r6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	   frozensetR2   R   R    R>   R<   R   t	   neighborsR?   R.   R
   R   (	   R   R8   R$   R@   R   RA   RC   t   new_clique_wanna_beRD   (    (    s:   lib/python2.7/site-packages/networkx/algorithms/chordal.pyR#   @  s.    			(   R   t   syst   networkxR
   t   networkx.utilsR    t   joint   __authors__t   __all__t   NetworkXExceptionR   R   t   maxsizeR   R   R   R.   R4   R<   R=   R   R#   (    (    (    s:   lib/python2.7/site-packages/networkx/algorithms/chordal.pyt   <module>   s&   		6N	*	,				$