
    \Mh[4                        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ej
                  Z ed           ed	          ej        d
                                     Zej        ej        fd            Zej        d             Zej        d             Zd Zd Zd Zdej        f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                       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__     [/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/networkx/algorithms/chordal.pyr
   r
      s           r   r
   directed
multigraphc                 v    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)Gs    r   r   r      s9    r 17||qt'**++q00r   c                 D   t          |           st          j        d          t          j        |           }|                    ||           t                      }t          |||          }|rO|\  }}}	|                    |           |D ]}
|
|k    r|                    ||
           t          |||          }|O|r`|                    |           | |         D ]B}t          |t          | |                   z            dk    r|                    |            nC|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NetworkXErrorGraphadd_edgesetr   updateaddr   )r   sttreewidth_boundHinduced_nodestripletuvwns              r   r   r   \   sJ   p a== ><===
AJJq!EEM&q!_==G
 B	AqW%%% 	! 	!AAvv

1a   *1aAA  B  !1 	 	A=3qt99,--22!!!$$$ 3 r   c              #   j   K    fdt                     D             D ]}|                                dk    rPt          j        |          dk    rt          j        d          t          |                                          V  kt          |                                          }t          |          }|	                    |           |h}|h}|rt          |||          }|	                    |           |                    |           t          |                    |                    |z  }|                    |          }t          |          r/|                    |           ||k    st          |          V  |}nt          j        d          |t          |          V  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   f   K   | ]+}                     |                                          V  ,d S N)subgraphcopy).0cr   s     r   	<genexpr>z(chordal_graph_cliques.<locals>.<genexpr>   s9      DDqajjmm  ""DDDDDDr      r   r   N)r   number_of_nodesr   number_of_selfloopsr    	frozensetr   r#   r   remove_max_cardinality_noder%   	neighborsr3   _is_complete_graph)r   C
unnumberedr-   numberedclique_wanna_benew_clique_wanna_besgs   `       r   r   r      s     \ EDDD,@,C,CDDD - -!##%a((1,,&'DEEEAGGII&&&&&&QWWYYJ!!$$Aa   sH cO J)!ZBB!!!$$$Q&)!++a..&9&9H&D#ZZ00%b)) J'++A..../AA'88888&9OO*+HIII  J O,,,,,,1- -r   c                     t          |           st          j        d          d}t          j        |           D ]}t	          |t          |                    } |dz
  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   r8   )r   r   r    r   maxr   )r   
max_cliquecliques      r   r	   r	      se    Z a== ><===J*1-- 2 2S[[11

>r   c                     t          j        |           dk    rt          j        d          |                                 }|dk     rdS |                                 }||dz
  z  dz  }||k    S )z&Returns True if G is a complete graph.r   z'Self loop found in _is_complete_graph()r   Tr8   )r   r:   r    r9   number_of_edges)r   r/   e	max_edgess       r   r?   r?   +  sv    	a  1$$HIII	A1uut	Aa!e!I	>r   c                     t          |           }| D ]W}|t          t          | |                                                   |gz             z
  }|r||                                fc S XdS )z5Given a non-complete graph G, returns a missing edge.N)r#   listkeyspop)r   r   r,   missings       r   _find_missing_edgerT   7  sy    FFE & &#d1Q499;;//1#5666 	&w{{}}%%%%	&& &r   c                 l    d}|D ]-}t          fd| |         D                       }||k    r|}|}.|S )z`Returns a the node in choices that has more connections in G
    to nodes in wanna_connect.
    rG   c                     g | ]}|v |	S r   r   )r5   ywanna_connects     r   
<listcomp>z)_max_cardinality_node.<locals>.<listcomp>F  s#    <<<Am););a);););r   )r   )r   choicesrX   
max_numberxnumbermax_cardinality_nodes     `    r   r=   r=   @  s\     J % %<<<<1<<<==JJ#$ r   c                 b   t          |           dk    rt          j        d          t          |           }|t	          |           }|                    |           |h}d}|rt          | ||          }|                    |           |                    |           t          | |                   |z  }|                     |          }t          |          r;t          |t          |                    }||k    rt          j        d|           nt          |          \  }	}
|	||
fS |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.
    r   zGraph has no nodes.NrG   ztreewidth_bound exceeded: r   )r   r   NetworkXPointlessConceptr#   r   r<   r=   r%   r3   r?   rH   r
   rT   )r   r&   r(   rA   rB   current_treewidthr-   rC   rE   r,   r.   s              r   r   r   M  sN    1vv{{)*?@@@QJya  asH
 !!Z::!Qad))h.ZZ((b!! 	 #$5s?7K7K L L ?227D1BDD   3 (++FQq!9#  $ 2r   T)returns_graphc           	         |                                  }t                              |d          }t          j        |          r||fS t                      }t                              |                                d          t          |                                          }t          t          |                                          dd          D ]}t          |fd          }|                    |           |||<   g }|D ]}|                     ||          r|                    |           .|         fd|D             }	t          j        |                    |	||gz             ||          r,|                    |           |                    ||f           |D ]}
|
xx         dz  cc<   |                    |           ||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)
    r   rG   c                     |          S r2   r   )nodeweights    r   <lambda>z+complete_to_chordal_graph.<locals>.<lambda>  s    6$< r   )keyc                 ,    g | ]}|         k     |S r   r   )r5   re   rf   y_weights     r   rY   z-complete_to_chordal_graph.<locals>.<listcomp>  s.       !9P9PD9P9P9Pr   r8   )r4   dictfromkeysr   r   r#   r   rP   ranger   rH   r<   has_edgeappendhas_pathr3   r%   add_edges_from)r   r)   alphachordsunnumbered_nodesizupdate_nodesrW   lower_nodesre   rf   rj   s              @@r   r   r   t  s   T 	
AMM!QE	}Q %xUUF]]17799a((FAGGII3qwwyy>>1b))   &?&?&?&?@@@"""a! 	' 	'Azz!Q 
'##A&&&& "!9    %5   ;qzz+A*>??AFF ' ''***JJ1v&&&  	 	D4LLLALLLL	Ve8Or   )r   sysnetworkxr   networkx.algorithms.componentsr   networkx.utilsr   r   __all__NetworkXExceptionr
   _dispatchabler   maxsizer   r   r	   r?   rT   r=   r   r   r   r   r   <module>r      s    


     ? ? ? ? ? ? A A A A A A A A      R%9   
 Z  \""81 81  #" ! 81v 03 L L L L^ E- E- E-P 2 2 2j	 	 	& & &
  
  
  #' $ $ $ $N Z  %%%E E &% ! E E Er   