
    h                      D   S r SSKrSSKrSSKJrJrJr  SSKrSSK	J
r
  SS/r\
" S5      \
" S5      \R                  " S	S
9S 5       5       5       r\
" S5      \
" S5      \R                  " S	S
9S 5       5       5       r " S S5      rS r\R                  " S	S
9\4S j5       rg)a,  Functions for computing treewidth decomposition.

Treewidth of an undirected graph is a number associated with the graph.
It can be defined as the size of the largest vertex set (bag) in a tree
decomposition of the graph minus one.

`Wikipedia: Treewidth <https://en.wikipedia.org/wiki/Treewidth>`_

The notions of treewidth and tree decomposition have gained their
attractiveness partly because many graph and network problems that are
intractable (e.g., NP-hard) on arbitrary graphs become efficiently
solvable (e.g., with a linear time algorithm) when the treewidth of the
input graphs is bounded by a constant [1]_ [2]_.

There are two different functions for computing a tree decomposition:
:func:`treewidth_min_degree` and :func:`treewidth_min_fill_in`.

.. [1] Hans L. Bodlaender and Arie M. C. A. Koster. 2010. "Treewidth
      computations I.Upper bounds". Inf. Comput. 208, 3 (March 2010),259-275.
      http://dx.doi.org/10.1016/j.ic.2009.03.008

.. [2] Hans L. Bodlaender. "Discovering Treewidth". Institute of Information
      and Computing Sciences, Utrecht University.
      Technical Report UU-CS-2005-018.
      http://www.cs.uu.nl

.. [3] K. Wang, Z. Lu, and J. Hicks *Treewidth*.
      https://web.archive.org/web/20210507025929/http://web.eecs.utk.edu/~cphill25/cs594_spring2015_projects/treewidth.pdf

    N)heapifyheappopheappush)not_implemented_fortreewidth_min_degreetreewidth_min_fill_indirected
multigraphT)returns_graphc                 :   ^ [        U 5      m[        U U4S j5      $ )a  Returns a treewidth decomposition using the Minimum Degree heuristic.

The heuristic chooses the nodes according to their degree, i.e., first
the node with the lowest degree is chosen, then the graph is updated
and the corresponding node is removed. Next, a new node with the lowest
degree is chosen, and so on.

Parameters
----------
G : NetworkX graph

Returns
-------
Treewidth decomposition : (int, Graph) tuple
      2-tuple with treewidth and the corresponding decomposed tree.
c                 &   > TR                  U 5      $ N)	best_node)graphdeg_heuristics    ]/var/www/html/env/lib/python3.13/site-packages/networkx/algorithms/approximation/treewidth.py<lambda>&treewidth_min_degree.<locals>.<lambda>?   s    ]-D-DU-K    )MinDegreeHeuristictreewidth_decomp)Gr   s    @r   r   r   *   s    ( 'q)MAKLLr   c                 "    [        U [        5      $ )a  Returns a treewidth decomposition using the Minimum Fill-in heuristic.

The heuristic chooses a node from the graph, where the number of edges
added turning the neighborhood of the chosen node into clique is as
small as possible.

Parameters
----------
G : NetworkX graph

Returns
-------
Treewidth decomposition : (int, Graph) tuple
    2-tuple with treewidth and the corresponding decomposed tree.
)r   min_fill_in_heuristic)r   s    r   r   r   B   s    & A455r   c                   $    \ rS rSrSrS rS rSrg)r   X   a1  Implements the Minimum Degree heuristic.

The heuristic chooses the nodes according to their degree
(number of neighbors), i.e., first the node with the lowest degree is
chosen, then the graph is updated and the corresponding node is
removed. Next, a new node with the lowest degree is chosen, and so on.
c                    Xl         / U l        / U l        [        R                  " 5       U l        U H?  nU R                  R                  [        X   5      [        U R                  5      U45        MA     [        U R                  5        g r   )	_graph_update_nodes_degreeq	itertoolscountappendlennextr   )selfr   ns      r   __init__MinDegreeHeuristic.__init__a   sf      __&
 AMM  #eh-djj1A1!EF r   c                 V   U R                    H:  n[        U R                  [        X   5      [	        U R
                  5      U45        M<     U R                  (       aN  [        U R                  5      u  p4nXQ;  d  [        X   5      U:w  a  MA  U[        U5      S-
  :X  a  g X   U l         U$ g )N   )r   r   r    r$   r%   r"   r   )r&   r   r'   
min_degree_	elim_nodes         r   r   MinDegreeHeuristic.best_nodeo   s    ##AT]]S]D4Da$HI $
 mm)0)?&ZI%U-=)>*)Ls5zA~- "'!1D r   )r    r   r   r"   N)__name__
__module____qualname____firstlineno____doc__r(   r   __static_attributes__ r   r   r   r   X   s    r   r   c                 Z  ^  [        T 5      S:X  a  gSn[        R                  n[        T U 4S jS9n[        T US      5      nU[        T 5      S-
  :X  a  gU HO  nSnT U   nU H%  nU[        UT U   -
  5      S-
  -  nUSU-  :  d  M%    O   US-  nXb:  d  MA  US:X  a  Us  $ UnUnMQ     U$ )ab  Implements the Minimum Degree heuristic.

Returns the node from the graph, where the number of edges added when
turning the neighborhood of the chosen node into clique is as small as
possible. This algorithm chooses the nodes using the Minimum Fill-In
heuristic. The running time of the algorithm is :math:`O(V^3)` and it uses
additional constant memory.r   Nc                     > [        TU    5      $ r   )r$   )xr   s    r   r   'min_fill_in_heuristic.<locals>.<lambda>   s    #eAh-r   )keyr+      )r$   sysmaxsizesorted)	r   min_fill_in_nodemin_fill_innodes_by_degreer,   nodenum_fill_innbrsnbrs	   `        r   r   r      s     5zQ++K U(?@OU?1-./J SZ!^#T{C 3teCj01A55Ka+o-  	q$a%K#!  $ r   c                    U  Vs0 s H  o"[        X   5      U1-
  _M     nn/ nU" U5      nUb  X5   n[        R                  " US5       H"  u  pxXU   ;  d  M  X7   R                  U5        M$     UR	                  XV45        X5    H  nX7   R                  U5        M     X5	 U" U5      nUb  M  [        R                  " 5       n	[        UR                  5       5      n
U	R                  U
5        [        U
5      S-
  nU(       a  UR                  5       u  pSnU	R                   H  nXn::  d  M
  Un  O   Uc  U
nUR                  U5        [        U5      n[        U[        U5      S-
  5      nU	R                  X5        U(       a  M  X4$ s  snf )a  Returns a treewidth decomposition using the passed heuristic.

Parameters
----------
G : NetworkX graph
heuristic : heuristic function

Returns
-------
Treewidth decomposition : (int, Graph) tuple
    2-tuple with treewidth and the corresponding decomposed tree.
Nr<   r+   )setr!   permutationsaddr#   removenxGraph	frozensetkeysadd_noder$   popnodesmaxadd_edge)r   	heuristicr'   r   
node_stackr.   rE   uvdecomp	first_bag	treewidth	curr_nodeold_bagbagnew_bags                   r   r   r      s     *++AAD	QCE+ J % I

**43DAa Q 4
 	9+, !AHOOI& " e$	 
$ XXZF%**,'I
OOII"I
&NN, <<C{  
 ?G 	D/ 	3w<!#34	 	)/ *2 q ,s   F	)r4   r!   r=   heapqr   r   r   networkxrL   networkx.utilsr   __all___dispatchabler   r   r   r   r   r6   r   r   <module>re      s   >  
 , ,  .!#:
; Z \"%M & # !M* Z \"%6 & # !6&, ,^*Z %"7 G &Gr   