o
    ˷e(8                     @   s   d Z ddlZddlZddlZddlmZ ddlmZm	Z	 g d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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   R/var/www/ideatree/venv/lib/python3.10/site-packages/networkx/algorithms/chordal.pyr	      s    r	   directed
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   6r   c                 C   s   t | s	tdt| }||| t }t|||}|r@|\}}}	|| |D ]}
|
|kr7|||
 q+t|||}|s|rb|| | | D ]}t	|t| | @ dkra||  |S qK|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NetworkXErrorGraphadd_edgesetr   updateaddr   )r   sttreewidth_boundHinduced_nodestripletuvwnr   r   r   r   W   s0   5





r   c                 C   s"   d}t |t dd t| D S )a  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.
        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)
    >>> setlist = nx.chordal_graph_cliques(G)
    z$This will return a generator in 3.0.c                 S   s   h | ]}|qS r   r   .0cr   r   r   	<setcomp>   s    z(chordal_graph_cliques.<locals>.<setcomp>)warningswarnDeprecationWarning_chordal_graph_cliques)r   msgr   r   r   r      s   )r   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   maxr   )r   
max_cliquecliquer   r   r   r      s   ,
r   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   Tr4   )r   number_of_selfloopsr   number_of_nodesnumber_of_edges)r   r)   e	max_edgesr   r   r   _is_complete_graph  s   
r=   c                 C   sH   t | }| D ]}|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   nodesr&   missingr   r   r   _find_missing_edge  s   rC   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.
    r3   c                    s   g | ]}| v r|qS r   r   )r+   ywanna_connectr   r   
<listcomp>"  s    z)_max_cardinality_node.<locals>.<listcomp>)r   )r   choicesrF   
max_numberxnumbermax_cardinality_noder   rE   r   _max_cardinality_node  s   rM   c                 C   s   t | dkrt dt| }|du rt| }|| |h}d}|rft| ||}|| || t| | |@ }| |}t	|rYt
|t|}||krXt d| nt|\}	}
|	||
fS |s$d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   Nr3   ztreewidth_bound exceeded: r   )r   r8   r   r   r   removerM   r   subgraphr=   r5   r   r	   rC   )r   r    r"   
unnumberednumberedcurrent_treewidthr'   clique_wanna_besgr&   r(   r   r   r   r   )  s2   





r   c                 #   s    fddt  D D ]r}| dkr(t|dkr tdt| V  qt| }t|}|	| |h}|h}|ryt
|||}|	| || t|||@ }||}t|rr|| ||ksot|V  |}ntd|s?t|V  qdS )a_  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

    Returns
    -------
    iterator
        An iterator over 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)rO   copyr*   r   r   r   	<genexpr>{  s    z)_chordal_graph_cliques.<locals>.<genexpr>r4   r   r   N)r   r9   r   r8   r   	frozensetrA   r   r   rN   rM   r   	neighborsrO   r=   )r   CrP   r'   rQ   rS   new_clique_wanna_berT   r   r   r   r1   N  s4   -







r1   c              	      s.  |   }dd |D }t|r||fS t }dd | D  t| }tt| ddD ]]}t| fddd}|	| |||< g }|D ]6}| 
||rW|| qI |  fd	d
|D }	t||	||g ||r|| |||f qI|D ]
}
 |
  d7  < qq0|| ||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      i | ]}|d qS r   r   r+   noder   r   r   
<dictcomp>      z-complete_to_chordal_graph.<locals>.<dictcomp>c                 S   r\   r]   r   r^   r   r   r   r`     ra   r   r3   c                    s    |  S rU   r   )r_   )weightr   r   <lambda>  s    z+complete_to_chordal_graph.<locals>.<lambda>)keyc                    s   g | ]
} | k r|qS r   r   r^   rb   y_weightr   r   rG     s    z-complete_to_chordal_graph.<locals>.<listcomp>r4   )rV   r   r   r   rA   r>   ranger   r5   rN   has_edgeappendhas_pathrO   r   add_edges_from)r   r#   alphachordsunnumbered_nodesizupdate_nodesrD   lower_nodesr_   r   re   r   r
     s8   )



r
   )r   sysr.   networkxr   networkx.algorithms.componentsr   networkx.utilsr   r   __all__NetworkXExceptionr	   r   maxsizer   r   r   r=   rC   rM   r   r1   r
   r   r   r   r   <module>   s*    
7M.5	%H