
    hc4                        S r SSKrSSKrSSKJr  SSKJrJr  / SQr	 " S S\R                  5      r\" S5      \" S	5      \R                  S
 5       5       5       r\R                  \R                  4S j5       r\R                  S 5       r\R                  S 5       rS rS rS rS\R                  4S jr\" S5      \R                  " SS9S 5       5       rg)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                       \ rS rSrSrSrg)r
      zRException raised when a treewidth bound has been provided and it has
been exceeded N)__name__
__module____qualname____firstlineno____doc____static_attributes__r       M/var/www/html/env/lib/python3.13/site-packages/networkx/algorithms/chordal.pyr
   r
      s    r   r
   directed
multigraphc                 d    [        U R                  5      S::  a  g[        [        U 5      5      S:H  $ )ul  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      s.    r 177|q'*+q00r   c                    [        U 5      (       d  [        R                  " S5      e[        R                  " U 5      nUR	                  X5        [        5       n[        XAU5      nU(       aL  Uu  pxn	UR                  U5        U H  n
X:w  d  M
  UR	                  X5        M     [        XAU5      nU(       a  ML  U(       aM  UR                  U5        X    H4  n[        U[        X   5      -  5      S:X  d  M"  UR                  U5          U$    U$ )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   \   s    p a==<==
AJJqEM&q_=G
	qW%Av

1   +1A ' !A=3qt9,-2!!!$	  r   c              #     ^ #    U 4S j[        T 5       5        GHe  nUR                  5       S:X  aM  [        R                  " U5      S:  a  [        R                  " S5      e[        UR                  5       5      v   Me  [        UR                  5       5      n[        U5      nUR                  U5        U1nU1nU(       a  [        XU5      nUR                  U5        UR                  U5        [        UR                  U5      5      U-  nUR                  U5      n[        U5      (       a&  UR                  U5        Xe:  d  [        U5      v   UnO[        R                  " S5      eU(       a  M  [        U5      v   GMh     g7f)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

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   b   >#    U  H$  nTR                  U5      R                  5       v   M&     g 7fN)subgraphcopy).0cr   s     r   	<genexpr>(chordal_graph_cliques.<locals>.<genexpr>   s'     D,Cqajjm  "",Cs   ,/   r   r    N)r   number_of_nodesr"   number_of_selfloopsr#   	frozensetr   r&   r   remove_max_cardinality_noder(   	neighborsr6   _is_complete_graph)r   C
unnumberedr0   numberedclique_wanna_benew_clique_wanna_besgs   `       r   r   r      s?    \ E,@,CD!#%%a(1,&&'DEEAGGI&&QWWYJ!!$Aa sH cO)!B!!!$Q&)!++a.&9H&D#ZZ0%b))'++A..A'88&9O**+HII * O,,1 Es   E,F1Fc                     [        U 5      (       d  [        R                  " S5      eSn[        R                  " U 5       H  n[	        U[        U5      5      nM     U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   
max_cliquecliques      r   r	   r	      sT    Z a==<==J**1-S[1
 .>r   c                     [         R                  " U 5      S:  a  [         R                  " S5      eU R                  5       nUS:  a  gU R	                  5       nXS-
  -  S-  nX#:H  $ )z&Returns True if G is a complete graph.r   z'Self loop found in _is_complete_graph()r!   Tr<   )r"   r>   r#   r=   number_of_edges)r   r2   e	max_edgess       r   rC   rC   +  se    	a 1$HII	A1u	A!e!I>r   c                     [        U 5      nU  HH  nU[        [        X   R                  5       5      U/-   5      -
  nU(       d  M7  X#R                  5       4s  $    g)z5Given a non-complete graph G, returns a missing edge.N)r&   listkeyspop)r   r   r/   missings       r   _find_missing_edgerX   7  sL    FE#d1499;/1#5667{{}%% r   c                     SnU H3  n[        X    Vs/ s H  oUU;   d  M
  UPM     sn5      nXc:  d  M/  UnUnM5     W$ s  snf )zXReturns a the node in choices that has more connections in G
to nodes in wanna_connect.
rK   )r   )r   choiceswanna_connect
max_numberxynumbermax_cardinality_nodes           r   rA   rA   @  sQ     J<Am);a<=J#$ 	 
  	 =s   	>
>
c                    [        U 5      S:X  a  [        R                  " S5      e[        U 5      nUc  [	        U 5      nUR                  U5        U1nSnU(       a  [        XU5      nUR                  U5        UR                  U5        [        X   5      U-  nU R                  U5      n[        U5      (       a4  [        U[        U5      5      nXR:  a  [        R                  " SU 35      eO[        U5      u  pXU
4$ U(       a  M  g)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.

It ignores any self loops.
r   zGraph has no nodes.rK   ztreewidth_bound exceeded: r   )r   r"   NetworkXPointlessConceptr&   r   r@   rA   r(   r6   rC   rL   r
   rX   )r   r)   r+   rE   rF   current_treewidthr0   rG   rI   r/   r1   s              r   r   r   M  s    1v{))*?@@QJya asH
!!:!Qad)h.ZZ(b!! #$5s?7K L 27701B0CD  3 (+FQ!9# *$ r   T)returns_graphc           	      n  ^ U R                  5       nU Vs0 s H  o"S_M     nn[        R                  " U5      (       a  X4$ [        5       nUR	                  5        Vs0 s H  o"S_M     snm[        UR	                  5       5      n[        [        UR	                  5       5      SS5       H  n[        UU4S jS9nUR                  U5        XcU'   / nU H  n	U R                  X5      (       a  UR                  U	5        M,  TU	   n
U Vs/ s H  nTU   U
:  d  M  UPM     nn[        R                  " UR                  XU	/-   5      X5      (       d  M  UR                  U	5        UR                  Xy45        M     U H  nTU==   S-  ss'   M     M     UR                  U5        X4$ s  snf s  snf s  snf )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   rK   c                    > TU    $ r5   r   )nodeweights    r   <lambda>+complete_to_chordal_graph.<locals>.<lambda>  s	    6$<r   )keyr<   )r7   r"   r   r&   r   rT   ranger   rL   r@   has_edgeappendhas_pathr6   r(   add_edges_from)r   r,   rg   alphachordsunnumbered_nodesizupdate_nodesr^   y_weightlower_nodesrh   s               @r   r   r   t  s   T 	
A!"#1WE#	}}QxUF"#''),)$Ag),FAGGI3qwwy>1b) &?@"a!Azz!##A& "!9%5%5T9PD%5   ;;qzz+A*>?FF ''*JJv& " !D4LAL !' ** V8O9 $ -s   F(F-	F2F2)r   sysnetworkxr"   networkx.algorithms.componentsr   networkx.utilsr   r   __all__NetworkXExceptionr
   _dispatchabler   maxsizer   r   r	   rC   rX   rA   r   r   r   r   r   <module>r      s     ? AR%9%9 
 Z \"81  # !81v 03 L L^ E- E-P 2 2j	&
  #' $N Z %E & !Er   