U
    ¹mœd|3  ã                   @   sÄ   d Z ddlZddlZddlmZ ddlmZmZ ddddd	d
gZ	G dd	„ d	ej
ƒZedƒedƒdd„ ƒƒZejfdd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdejfdd„Zedƒdd
„ ƒZdS )zÇ
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
é    N)Úconnected_components)Úarbitrary_elementÚnot_implemented_forÚ
is_chordalÚfind_induced_nodesÚchordal_graph_cliquesÚchordal_graph_treewidthÚNetworkXTreewidthBoundExceededÚcomplete_to_chordal_graphc                   @   s   e Zd ZdZdS )r	   zVException raised when a treewidth bound has been provided and it has
    been exceededN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r   r   úT/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/networkx/algorithms/chordal.pyr	      s   ZdirectedZ
multigraphc                 C   s   t t| ƒƒdkS )uÿ  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
    ------
    NetworkXNotImplemented
        The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.

    Examples
    --------
    >>> 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.
    r   )ÚlenÚ_find_chordality_breaker©ÚGr   r   r   r      s    6c                 C   sÄ   t | ƒst d¡‚t | ¡}| ||¡ tƒ }t|||ƒ}|r~|\}}}	| |¡ |D ]}
|
|krV| ||
¡ qVt|||ƒ}q:|rÀ| |¡ | | D ]*}t	|t| | ƒ@ ƒdkr”| |¡  qÀq”|S )aµ  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
    treewidth_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
    -------
    induced_nodes : 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
    --------
    >>> G = nx.Graph()
    >>> G = nx.generators.classic.path_graph(10)
    >>> induced_nodes = nx.find_induced_nodes(G, 1, 9, 2)
    >>> sorted(induced_nodes)
    [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
    úInput graph is not chordal.é   )
r   ÚnxÚNetworkXErrorZGraphZadd_edgeÚsetr   ÚupdateÚaddr   )r   ÚsÚtÚtreewidth_boundÚHZinduced_nodesÚtripletÚuÚvÚwÚnr   r   r   r   V   s(    5





c                 #   sþ   ‡ fdd„t ˆ ƒD ƒD ]â}| ¡ dkrNt |¡dkr>t d¡‚t| ¡ ƒV  qt| ¡ ƒ}t|ƒ}| 	|¡ |h}|h}|rît
|||ƒ}| 	|¡ | |¡ t| |¡ƒ|@ }| |¡}t|ƒrâ| |¡ ||ksÜt|ƒV  |}qxt d¡‚qxt|ƒV  qdS )aU  Returns all 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

    Yields
    ------
    frozenset of nodes
        Maximal cliques, each of which is a frozenset of
        nodes in `G`. The order of cliques is arbitrary.

    Raises
    ------
    NetworkXError
        The algorithm does not support DiGraph, MultiGraph and MultiDiGraph.
        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
    --------
    >>> 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)
    >>> cliques = [c for c in chordal_graph_cliques(G)]
    >>> cliques[0]
    frozenset({1, 2, 3})
    c                 3   s   | ]}ˆ   |¡ ¡ V  qd S ©N)ÚsubgraphÚcopy)Ú.0Úcr   r   r   Ú	<genexpr>Ð   s     z(chordal_graph_cliques.<locals>.<genexpr>é   r   r   N)r   Únumber_of_nodesr   Únumber_of_selfloopsr   Ú	frozensetÚnodesr   r   ÚremoveÚ_max_cardinality_noder   Z	neighborsr&   Ú_is_complete_graph)r   ÚCÚ
unnumberedr"   ÚnumberedÚclique_wanna_beZnew_clique_wanna_beÚsgr   r   r   r   £   s.    -






c                 C   s<   t | ƒst d¡‚d}t | ¡D ]}t|t|ƒƒ}q |d S )a¼  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.
        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
    --------
    >>> 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
    r   éÿÿÿÿr+   )r   r   r   r   Úmaxr   )r   Z
max_cliqueZcliquer   r   r   r   ë   s    ,
c                 C   sL   t  | ¡dkrt  d¡‚|  ¡ }|dk r,dS |  ¡ }||d  d }||kS )z&Returns True if G is a complete graph.r   z'Self loop found in _is_complete_graph()r   Tr+   )r   r-   r   r,   Znumber_of_edges)r   r$   ÚeZ	max_edgesr   r   r   r2      s    
r2   c                 C   sH   t | ƒ}| D ]6}|t t| |  ¡ ƒ|g ƒ }|r|| ¡ f  S qdS )z5Given a non-complete graph G, returns a missing edge.N)r   ÚlistÚkeysÚpop)r   r/   r!   Úmissingr   r   r   Ú_find_missing_edge,  s
    r?   c                    s<   d}|D ].}t ‡ fdd„| | D ƒƒ}||kr|}|}q|S )z`Returns a the node in choices that has more connections in G
    to nodes in wanna_connect.
    r8   c                    s   g | ]}|ˆ kr|‘qS r   r   )r(   Úy©Úwanna_connectr   r   Ú
<listcomp>;  s      z)_max_cardinality_node.<locals>.<listcomp>)r   )r   ÚchoicesrB   Z
max_numberÚxÚnumberZmax_cardinality_noder   rA   r   r1   5  s    r1   c                 C   sÎ   t  | ¡dkrt  d¡‚t| ƒ}|dkr0t| ƒ}| |¡ |h}d}|rÊt| ||ƒ}| |¡ | |¡ t| | ƒ|@ }|  |¡}t	|ƒr²t
|t|ƒƒ}||krÈt  d|› �¡‚qDt|ƒ\}	}
|	||
fS qDdS )a'  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.
    r   r   Nr8   ztreewidth_bound exceeded: r   )r   r-   r   r   r   r0   r1   r   r&   r2   r9   r   r	   r?   )r   r   r   r4   r5   Zcurrent_treewidthr"   r6   r7   r!   r#   r   r   r   r   B  s.    




ÿr   c              	      s0  |   ¡ }dd„ |D ƒ}t |¡r(||fS tƒ }dd„ | ¡ D ƒ‰ t| ¡ ƒ}tt| ¡ ƒddƒD ]¼}t|‡ fdd„d�}| 	|¡ |||< g }|D ]l}|  
||¡r®| |¡ q’ˆ | ‰‡ ‡fd	d
„|D ƒ}	t | |	||g ¡||¡r’| |¡ | ||f¡ q’|D ]}
ˆ |
  d7  < �qq`| |¡ ||fS )a  Return a copy of G completed to a chordal graph

    Adds edges to a copy of G to create a chordal graph. A graph G=(V,E) is
    called chordal if for each cycle with length bigger than 3, there exist
    two non-adjacent nodes connected by an edge (called a chord).

    Parameters
    ----------
    G : NetworkX graph
        Undirected graph

    Returns
    -------
    H : NetworkX graph
        The chordal enhancement of G
    alpha : Dictionary
            The elimination ordering of nodes of G

    Notes
    -----
    There are different approaches to calculate the chordal
    enhancement of a graph. The algorithm used here is called
    MCS-M and gives at least minimal (local) triangulation of graph. Note
    that this triangulation is not necessarily a global minimum.

    https://en.wikipedia.org/wiki/Chordal_graph

    References
    ----------
    .. [1] Berry, Anne & Blair, Jean & Heggernes, Pinar & Peyton, Barry. (2004)
           Maximum Cardinality Search for Computing Minimal Triangulations of
           Graphs.  Algorithmica. 39. 287-298. 10.1007/s00453-004-1084-3.

    Examples
    --------
    >>> from networkx.algorithms.chordal import complete_to_chordal_graph
    >>> G = nx.wheel_graph(10)
    >>> H, alpha = complete_to_chordal_graph(G)
    c                 S   s   i | ]
}|d “qS ©r   r   ©r(   Únoder   r   r   Ú
<dictcomp>‘  s      z-complete_to_chordal_graph.<locals>.<dictcomp>c                 S   s   i | ]
}|d “qS rG   r   rH   r   r   r   rJ   •  s      r   r8   c                    s   ˆ |  S r%   r   )rI   )Úweightr   r   Ú<lambda>™  ó    z+complete_to_chordal_graph.<locals>.<lambda>)Úkeyc                    s   g | ]}ˆ | ˆk r|‘qS r   r   rH   ©rK   Zy_weightr   r   rC   £  s     z-complete_to_chordal_graph.<locals>.<listcomp>r+   )r'   r   r   r   r/   r;   Úranger   r9   r0   Zhas_edgeÚappendZhas_pathr&   r   Zadd_edges_from)r   r   ÚalphaZchordsZunnumbered_nodesÚiÚzZupdate_nodesr@   Zlower_nodesrI   r   rO   r   r
   g  s4    )

ÿ

)r   ÚsysZnetworkxr   Znetworkx.algorithms.componentsr   Znetworkx.utilsr   r   Ú__all__ZNetworkXExceptionr	   r   Úmaxsizer   r   r   r2   r?   r1   r   r
   r   r   r   r   Ú<module>   s0   ú
7MH5	%