a
    h3                     @   s   d 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	ejd
d ZejejfddZejdd Zejdd Zdd Zdd Zdd ZdejfddZedej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   I/var/www/auris/lib/python3.9/site-packages/networkx/algorithms/chordal.pyr	      s   r	   ZdirectedZ
multigraphc                 C   s"   t | jdkrd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]_.

    Self loops are ignored.

    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.
       Tr   )lennodes_find_chordality_breakerGr   r   r   r      s    9r   c                 C   s   t | stdt| }||| t }t|||}|r~|\}}}	|| |D ]}
|
|krV|||
 qVt|||}q:|r|| | | D ]*}t	|t| | @ dkr||  qq|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.

    Self Loops are ignored

    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_nodesZtripletuvwnr   r   r   r   [   s(    8





r   c                 #   s    fddt  D D ]}| dkrNt|dkr>tdt| V  qt| }t|}|	| |h}|h}|rt
|||}|	| || t|||@ }||}t|r|| ||kst|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>       z(chordal_graph_cliques.<locals>.<genexpr>   r   r   N)r   number_of_nodesr   number_of_selfloopsr   	frozensetr   r   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.    .






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   r   maxr   )r   Z
max_cliqueZ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   Tr-   )r   r/   r   r.   Znumber_of_edges)r   r%   eZ	max_edgesr   r   r   r3   *  s    
r3   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_edge6  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.
    r9   c                    s   g | ]}| v r|qS r   r   )r)   ywanna_connectr   r   
<listcomp>E  r,   z)_max_cardinality_node.<locals>.<listcomp>)r   )r   choicesrC   Z
max_numberxnumberZmax_cardinality_noder   rB   r   r2   ?  s    r2   c                 C   s   t | }|du rt| }|| |h}d}|rt| ||}|| || t | | |@ }| |}t|rt|t|}||krt	
d| q,t|\}	}
|	||
fS q,dS )aG  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.

    It ignores any self loops.
    Nr9   ztreewidth_bound exceeded: r   )r   r   r1   r2   r   r'   r3   r:   r   r   r	   r@   )r   r   r    r5   r6   Zcurrent_treewidthr#   r7   r8   r"   r$   r   r   r   r   L  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>  r,   z-complete_to_chordal_graph.<locals>.<dictcomp>c                 S   s   i | ]
}|d qS rH   r   rI   r   r   r   rK     r,   r   r9   c                    s    |  S r&   r   )rJ   )weightr   r   <lambda>  r,   z+complete_to_chordal_graph.<locals>.<lambda>)keyc                    s   g | ]} | k r|qS r   r   rI   rL   Zy_weightr   r   rD     s   z-complete_to_chordal_graph.<locals>.<listcomp>r-   )r(   r   r   r   r   r<   ranger   r:   r1   Zhas_edgeappendZhas_pathr'   r   Zadd_edges_from)r   r!   alphaZchordsZunnumbered_nodesizZupdate_nodesrA   Zlower_nodesrJ   r   rO   r   r
   q  s4    *



r
   )r   sysZnetworkxr   Znetworkx.algorithms.componentsr   Znetworkx.utilsr   r   __all__ZNetworkXExceptionr	   	_dispatchr   maxsizer   r   r   r3   r@   r2   r   r
   r   r   r   r   <module>   s.   
;O
H
5	%