
    wgc4                        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y)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y)r
   zVException raised when a treewidth bound has been provided and it has
    been exceededN)__name__
__module____qualname____doc__     `/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/networkx/algorithms/chordal.pyr
   r
      s    r   r
   directed
multigraphc                 b    t        | j                        dk  ry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      s.    r 177|q'*+q00r   c                    t        |       st        j                  d      t        j                  |       }|j	                  ||       t               }t        |||      }|rF|\  }}}	|j                  |       |D ]  }
|
|k7  s	|j	                  ||
        t        |||      }|rF|rL|j                  |       | |   D ]3  }t        |t        | |         z        dk(  s!|j                  |        |S  |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   \   s   p a=<==
AJJq!EM&q!_=G
	AqW% 	!AAv

1a 	! +1aA  !1 	A=3qt9,-2!!!$		 r   c              #      K    fdt               D        D ]O  }|j                         dk(  rIt        j                  |      dkD  rt        j                  d      t        |j                                `t        |j                               }t        |      }|j                  |       |h}|h}|rt        |||      }|j                  |       |j                  |       t        |j                  |            |z  }|j                  |      }t        |      r&|j                  |       ||k\  st        |       |}nt        j                  d      |rt        |       R yw)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   \   K   | ]#  }j                  |      j                          % y wN)subgraphcopy).0cr   s     r   	<genexpr>z(chordal_graph_cliques.<locals>.<genexpr>   s"     Dqajjm  "Ds   ),   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      sC    \ E,@,CD -!#%%a(1,&&'DEEAGGI&&QWWYJ!!$Aa sH cO)!ZB!!!$Q&)!++a.&9H&D#ZZ0%b)'++A../A'88&9O**+HII  O,,1-s   EE,E,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	      sW    Z a=<==J**1- 2S[1
2>r   c                     t        j                  |       dkD  rt        j                  d      | j                         }|dk  ry| j	                         }||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?   +  si    	a 1$HII	A1u	Aa!e!I	>r   c                     t        |       }| D ]D  }|t        t        | |   j                               |gz         z
  }|s2||j                         fc S  y)z5Given a non-complete graph G, returns a missing edge.N)r#   listkeyspop)r   r   r,   missings       r   _find_missing_edgerT   7  sS    FE &#d1Q499;/1#566w{{}%%&r   c                 x    d}|D ]-  }t        | |   D cg c]	  }||v s| c}      }||kD  s*|}|}/ S c c}w )z`Returns a the node in choices that has more connections in G
    to nodes in wanna_connect.
    rG   )r   )r   choiceswanna_connect
max_numberxynumbermax_cardinality_nodes           r   r=   r=   @  sX     J %1<Am);a<=JJ#$ 	%
  	 =s   	7
7
c                    t        |       dk(  rt        j                  d      t        |       }|t	        |       }|j                  |       |h}d}|rt        | ||      }|j                  |       |j                  |       t        | |         |z  }| j                  |      }t        |      r2t        |t        |            }||kD  r+t        j                  d|       t        |      \  }	}
|	||
fS |ry)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.rG   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  s    1v{))*?@@QJya asH
!!Z:!Qad)h.ZZ(b! #$5s?7K L ?27701B0CD  (+FQq!9# $ r   T)returns_graphc           	      <   | j                         }|D ci c]  }|d }}t        j                  |      r||fS t               }|j	                         D ci c]  }|d c}t        |j	                               }t        t        |j	                               dd      D ]  }t        |fd      }|j                  |       |||<   g }|D ]  }	| j                  |	|      r|j                  |	       '|	   }
|D cg c]  }|   |
k  s| }}t        j                  |j                  |||	gz         |	|      sp|j                  |	       |j                  ||	f        |D ]  }|xx   dz  cc<     |j                  |       ||fS c c}w c c}w c c}w )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   )keyr8   )r4   r   r   r#   r   rP   ranger   rH   r<   has_edgeappendhas_pathr3   r%   add_edges_from)r   r)   rc   alphachordsunnumbered_nodesizupdate_nodesrZ   y_weightlower_nodesrd   s               @r   r   r   t  s   T 	
A!"#T1W#E#	}}Q%xUF"#''),$dAg,FAGGI3qwwy>1b)  &?@"a! 	'Azz!Q##A& "!9%5!9PD  ;;qzz+A*>?AF ''*JJ1v&	' ! 	D4LAL	'* Ve8O9 $ -s   
F
F>FF)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R%9%9 
 Z \"81  # !81v 03 L L^ E- E-P 2 2j	&
  #' $N Z %E & !Er   