
    \h/                     r    S SK Jr  S SKJr  S SKJr  S SKJr  S SKJ	r	J
r
  S SKJr  S SKJr   " S S	\5      rg
)    )Basic)Tuple)Array_sympify)flatteniterable)as_int)defaultdictc                       \ rS rSrSrSrSrSrSr\	S 5       r
\	S 5       r\	S 5       r\	S 5       r\	S 5       r\S	 5       r\S
 5       r\S 5       rS r\S 5       rS rSS jrSS jrSrg)Prufer   ap  
The Prufer correspondence is an algorithm that describes the
bijection between labeled trees and the Prufer code. A Prufer
code of a labeled tree is unique up to isomorphism and has
a length of n - 2.

Prufer sequences were first used by Heinz Prufer to give a
proof of Cayley's formula.

References
==========

.. [1] https://mathworld.wolfram.com/LabeledTree.html

Nc                     U R                   c.  U R                  U R                  SS U R                  5      U l         U R                   $ )a  Returns Prufer sequence for the Prufer object.

This sequence is found by removing the highest numbered vertex,
recording the node it was attached to, and continuing until only
two vertices remain. The Prufer sequence is the list of recorded nodes.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]).prufer_repr
[3, 3, 3, 4]
>>> Prufer([1, 0, 0]).prufer_repr
[1, 0, 0]

See Also
========

to_prufer

N)_prufer_repr	to_prufer
_tree_reprnodesselfs    R/var/www/auris/envauris/lib/python3.13/site-packages/sympy/combinatorics/prufer.pyprufer_reprPrufer.prufer_repr    s<    . $ $tq/A4:: ND       c                 z    U R                   c#  U R                  U R                  SS 5      U l         U R                   $ )aB  Returns the tree representation of the Prufer object.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]).tree_repr
[[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]
>>> Prufer([1, 0, 0]).tree_repr
[[1, 2], [0, 1], [0, 3], [0, 4]]

See Also
========

to_tree

N)r   to_treer   r   s    r   	tree_reprPrufer.tree_repr;   s3    & ??""ll4+<+<Q+?@DOr   c                     U R                   $ )zReturns the number of nodes in the tree.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]]).nodes
6
>>> Prufer([1, 0, 0]).nodes
5

)_nodesr   s    r   r   Prufer.nodesR   s     {{r   c                 ^    U R                   c  U R                  5       U l         U R                   $ )a  Returns the rank of the Prufer sequence.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> p = Prufer([[0, 3], [1, 3], [2, 3], [3, 4], [4, 5]])
>>> p.rank
778
>>> p.next(1).rank
779
>>> p.prev().rank
777

See Also
========

prufer_rank, next, prev, size

)_rankprufer_rankr   s    r   rankPrufer.rankb   s(    , ::))+DJzzr   c                 n    U R                  U R                  5      R                  5       R                  S-   $ )zReturn the number of possible trees of this Prufer object.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer([0]*4).size == Prufer([6]*4).size == 1296
True

See Also
========

prufer_rank, rank, next, prev

   )prevr$   r   s    r   sizePrufer.size|   s+    " yy#((*//!33r   c                    [        [        5      n/ nU  H!  nX$S   ==   S-  ss'   X$S   ==   S-  ss'   M#     [        US-
  5       H  n[        U5       H  nX&   S:X  d  M    O   SnU  H$  nWUS   :X  a  US   nOXdS   :X  a  US   nUc  M$    O   UR                  U5        WU4 H+  nX(==   S-  ss'   X(   (       a  M  UR	                  U5        M-     U R                  W5        M     U$ )a}  Return the Prufer sequence for a tree given as a list of edges where
``n`` is the number of nodes in the tree.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [0, 2], [0, 3]])
>>> a.prufer_repr
[0, 0]
>>> Prufer.to_prufer([[0, 1], [0, 2], [0, 3]], 4)
[0, 0]

See Also
========
prufer_repr: returns Prufer sequence of a Prufer object.

r   r'      N)r   intrangeappendpopremove)	treendLedgeixyjs	            r   r   Prufer.to_prufer   s    ( D 1gJ!OJ1gJ!OJ  q1uA1X419  AQ<QAq'\QA=  HHQKV	ttEE!H  KK) * r   c                    / n/ n[        U 5      S-   n[        S 5      nU  H  nXE==   S-  ss'   M     U  HS  n[        U5       H  nXG   S:X  d  M    O   XF==   S-  ss'   UW==   S-  ss'   UR                  [	        Xg/5      5        MU     [        U5       Vs/ s H  odU   S:X  d  M  UPM     sn=(       d    SS/nUR                  U5        U$ s  snf )a  Return the tree (as a list of edges) of the given Prufer sequence.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([0, 2], 4)
>>> a.tree_repr
[[0, 1], [0, 2], [2, 3]]
>>> Prufer.to_tree([0, 2])
[[0, 1], [0, 2], [2, 3]]

References
==========

.. [1] https://hamberg.no/erlend/posts/2010-11-06-prufer-sequence-compact-tree-representation.html

See Also
========
tree_repr: returns tree representation of a Prufer object.

r,   c                      g)Nr'    r>   r   r   <lambda> Prufer.to_tree.<locals>.<lambda>   s    r   r'   r   )lenr   r.   r/   sorted)pruferr2   lastr3   r4   pr7   r:   s           r   r   Prufer.to_tree   s    0 K!O	"ADAID A1X419  DAIDaDAIDKKv'  !818atqy81;aVD 2s   C*Cc                     [        5       nU S   S   nU  HC  n[        [        U5      S-
  5       H%  nX4US-    u  pVXe:  a  XepeUR                  XV45        M'     ME     / n[        5       nS=p)U H\  n
UR	                  U
5        Ub  [        U
S   U5      OU
S   nU	b  [        U
S   U	5      OU
S   n	UR                  [        U
5      5        M^     [        [        X)S-   5      5      U-
  nU(       aP  U Vs/ s H  oDU-   PM	     nn[        U5      S:X  a  SUR                  5       -  nOS[        U5      -  n[        U5      eUS:w  a/  [        U5       H  u  pJU
 Vs/ s H  oU-
  PM	     snXt'   M     X-  n	[        U5      U	S-   4$ s  snf s  snf )a  Return a list of edges and the number of nodes from the given runs
that connect nodes in an integer-labelled tree.

All node numbers will be shifted so that the minimum node is 0. It is
not a problem if edges are repeated in the runs; only unique edges are
returned. There is no assumption made about what the range of the node
labels should be, but all nodes from the smallest through the largest
must be present.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer.edges([1, 2, 3], [2, 4, 5]) # a T
([[0, 1], [1, 2], [1, 3], [3, 4]], 5)

Duplicate edges are removed:

>>> Prufer.edges([0, 1, 2, 3], [1, 4, 5], [1, 4, 6]) # a K
([[0, 1], [1, 2], [1, 4], [2, 3], [4, 5], [4, 6]], 7)

r   r'   r,   NNode %s is missing.Nodes %s are missing.)setr.   rA   addupdateminmaxr/   listr0   rB   
ValueError	enumerate)runsenminrr7   abrvgotnmaxeimissingmsgr3   s                 r   edgesPrufer.edges   s   0 EAwqzA3q6A:&AE{5qqf	 '  eBJJrN'+'73r!ud#RUD'+'73r!ud#RUDIId2h	 
 eD(+,s2)01A4xG17|q +gkkm;-w?S/!19"2+-.2aT2. 'LDbz4!8## 2 /s   2FFc                     SnSn[        U R                  S-
  SS5       H%  nXU R                  U   -  -  nX R                  -  nM'     U$ )zComputes the rank of a Prufer sequence.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [0, 2], [0, 3]])
>>> a.prufer_rank()
0

See Also
========

rank, next, prev, size

r   r'      )r.   r   r   )r   rU   rE   r7   s       r   r#   Prufer.prufer_rank%  sS    " tzzA~r2.A4##A&&&AOA / r   c                    [        U5      [        U5      p[        [        5      n[        US-
  SS5       H  nX-  X4'   XU   -
  U-  nM     [	        [        [        U5      5       Vs/ s H  oCU   PM	     sn5      $ s  snf )zFinds the unranked Prufer sequence.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> Prufer.unrank(0, 4)
Prufer([0, 0])

ra   rb   )r
   r   r-   r.   r   rA   )r   r$   r3   r5   r7   s        r   unrankPrufer.unrank=  sv     )VD\4q1ub"%A8ADQ4K!#D & U3q6]3]t]3443s   'A<c                 &   US   (       a  [        US   5      O	[        5       nU4[        S USS  5       5      -   n[        R                  " U /UQ70 UD6n[        US   5      /nUS   (       a  [        US   S   5      (       a  US   S   (       d  [        S5      e[        U5      S:  a  US   nO[        [        US   5      5      n[        U5      S-   nU[        U5      :w  aS  [        [        U5      5      U-
  n[        U5      S:X  a  SUR                  5       -  nOS[        U5      -  n[        U5      eUS    V	s/ s H  n	[        U	5      PM     sn	Ul        XTl        U$ US   Ul        [        UR"                  5      S-   Ul        U$ s  sn	f )	a>  The constructor for the Prufer object.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer

A Prufer object can be constructed from a list of edges:

>>> a = Prufer([[0, 1], [0, 2], [0, 3]])
>>> a.prufer_repr
[0, 0]

If the number of nodes is given, no checking of the nodes will
be performed; it will be assumed that nodes 0 through n - 1 are
present:

>>> Prufer([[0, 1], [0, 2], [0, 3]], 4)
Prufer([[0, 1], [0, 2], [0, 3]], 4)

A Prufer object can be constructed from a Prufer sequence:

>>> b = Prufer([1, 3])
>>> b.tree_repr
[[0, 1], [1, 3], [2, 3]]

r   c              3   8   #    U  H  n[        U5      v   M     g 7f)Nr   ).0args     r   	<genexpr>!Prufer.__new__.<locals>.<genexpr>m  s     Ax}}s   r'   Nz-Prufer expects at least one edge in the tree.rH   rI   r,   )r   r   tupler   __new__rO   r	   rP   rA   rJ   r   rN   r.   r0   rB   r   r   r   )
clsargskw_argsarg0ret_objnnodesr   r\   r]   r7   s
             r   rn   Prufer.__new__P  sv   8 "&auT!W~egwAQRAAA--6d6g6T!W7xQ
++71: CE E4y1}aGDG,-UaSZ'!%-058G7|q(3gkkmC5wG$S/)377!;7a$q'7!;G#N  $(7G  !5!56:GN "<s    Fc                 \    [         R                  U R                  U-   U R                  5      $ )a<  Generates the Prufer sequence that is delta beyond the current one.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [0, 2], [0, 3]])
>>> b = a.next(1) # == a.next()
>>> b.tree_repr
[[0, 2], [0, 1], [1, 3]]
>>> b.rank
1

See Also
========

prufer_rank, rank, prev, size

r   re   r$   r   r   deltas     r   nextPrufer.next  s"    ( }}TYY.

;;r   c                 \    [         R                  U R                  U-
  U R                  5      $ )a4  Generates the Prufer sequence that is -delta before the current one.

Examples
========

>>> from sympy.combinatorics.prufer import Prufer
>>> a = Prufer([[0, 1], [1, 2], [2, 3], [1, 4]])
>>> a.rank
36
>>> b = a.prev()
>>> b
Prufer([1, 2, 0])
>>> b.rank
35

See Also
========

prufer_rank, rank, next, size

rw   rx   s     r   r(   Prufer.prev  s"    , }}TYY-tzz::r   )r   r"   r   )r'   )__name__
__module____qualname____firstlineno____doc__r   r   r   r"   propertyr   r   r   r$   r)   staticmethodr   r   r^   r#   classmethodre   rn   rz   r(   __static_attributes__r>   r   r   r   r      s     LJFE! !4  ,    2 4 4$ 0 0d * *X 3$ 3$j0 5 5$5n<,;r   r   N)
sympy.corer   sympy.core.containersr   sympy.tensor.arrayr   sympy.core.sympifyr   sympy.utilities.iterablesr   r	   sympy.utilities.miscr
   collectionsr   r   r>   r   r   <module>r      s(     ' $ ' 7 ' #h;U h;r   