K i/rddlmZddlmZddlmZddlmZddlm Z m Z ddl m Z ddl mZGdd eZy ) )Basic)Tuple)Array_sympify)flatteniterable)as_int) defaultdictceZdZdZdZdZdZdZedZ edZ edZ edZ edZ edZed Zed Zd Zed Zd ZddZddZy)Prufera 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|j.|j|jdd|j|_|jS)aHReturns 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_reprnodesselfs `/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/combinatorics/prufer.py prufer_reprzPrufer.prufer_repr s<.    $ $tq/A4:: ND    cx|j#|j|jdd|_|jS)aReturns 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)rto_treerrs r tree_reprzPrufer.tree_repr;s3& ?? ""ll4+<+>> 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 )_nodesrs rrz Prufer.nodesRs{{rc\|j|j|_|jS)aReturns 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_rankrs rrankz Prufer.rankbs(, :: ))+DJzzrcn|j|jjjdzS)a6Return 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 rs rsizez Prufer.size|s+"yy#((*//!33rctt}g}|D]"}||dxxdz cc<||dxxdz cc<$t|dz D]}t|D] }||dk(s nd}|D]!}|dk(r|d}n ||dk(r|d}|!n|j||fD]&}||xxdzcc<||r|j |(|j |S)aReturn 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. rr"N)r intrangeappendpopremove) treendLedgeixyjs rrzPrufer.to_prufers(    D d1gJ!OJ d1gJ!OJ   q1u A1X Q419 A Q<QA$q'\QA=   HHQKV ! tEE!H  KK ) *rcg}g}t|dz}td}|D]}||xxdz cc<|D]R}t|D] }||dk(s n||xxdzcc<|xxdzcc<|jt ||gTt|Dcgc] }||dk(s |c}xsddg}|j||Scc}w)aBReturn 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&cy)Nr"r7rrz Prufer.to_tree..srr"r)lenr r(r)sorted)pruferr,lastr-r.pr1r4s rrzPrufer.to_trees0 K!O  " A aDAID  (A1X Q419  aDAID aDAID KK1v ' (!81aqtqy1;aV D 2s  C%Cct}|dd}|D]E}tt|dz D])}|||dz\}}||kr||}}|j||f+Gg}t}dx}} |D]Y} |j | |t | d|n| d}| t | d| n| d} |jt| [tt|| dz|z } | rW| Dcgc]}||z } }t| dk(rd| jz} t| dt| z} t| |dk7r.t|D]\}} | D cgc]} | |z  c} ||<| |z} t|| dzfScc}wcc} w)aAReturn 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) rr"r&NNode %s is missing.Nodes %s are missing.) setr(r9addupdateminmaxr)listr*r: ValueError enumerate)runsenminrr1abrvgotnmaxeimissingmsgr-s redgesz Prufer.edgess0 EAwqz A3q6A:& AE{1q5aqAq!f    et B JJrN'+'73r!ud#RUD'+'73r!ud#RUD IId2h   eD$(+,s2 )01Aq4x1G17|q +gkkm;S/ !.w?S/ ! 19"2 /2+-.aT.1 / DLDbz4!8##2/s , F Fcd}d}t|jdz ddD]&}|||j|zz }||jz}(|S)a)Computes 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 rr")r(rr)rrLr=r1s rrzPrufer.prufer_rank%s\"  tzzA~r2. A 4##A&& &A OA rct|t|}}tt}t|dz ddD]}||z||<|||z |z}t tt |Dcgc]}|| c}Scc}w)zFinds the unranked Prufer sequence. Examples ======== >>> from sympy.combinatorics.prufer import Prufer >>> Prufer.unrank(0, 4) Prufer([0, 0]) rWrX)r r r'r(r r9)rr r-r/r1s runrankz Prufer.unrank=s)VD\4  q1ub"% $A!8AaD1Q4K!#D $U3q6]3qt3443s) A<c|drt|dn t}|ftd|ddDz}tj|g|i|}t |dg}|drt |ddr|dds tdt|dkDr|d}ntt|d}t|dz}|t|k7r\tt||z }t|dk(rd|jz}t|dt|z}t||dD cgc] } t | c} |_||_|S|d|_t|j"dz|_|Scc} w) aThe 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]] rc32K|]}t|yw)Nr).0args r z!Prufer.__new__..msAx}Asr"Nz-Prufer expects at least one edge in the tree.r?r@r&)rrtupler__new__rFr rGr9rArrEr(r*r:rrr) clsargskw_argsarg0ret_objnnodesrrSrTr1s rrazPrufer.__new__Ps8"&auT!W~egwAQRAAA--6d6g6T!W  7xQ +71: CEE4y1}aGDG,-UaSZ'!%-058G7|q(3gkkmC%S/)6wG$S/)377!;a$q'!;G #GN$(7G  !5!56:GN "c\tj|j|z|jS)aGenerates 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 rZr rrdeltas rnextz Prufer.nexts"(}}TYY. ;;rc\tj|j|z |jS)aGenerates 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 rirjs rr#z Prufer.prevs",}}TYY-tzz::r)r")__name__ __module__ __qualname____doc__rrrrpropertyrrrr r$ staticmethodrrrUr classmethodrZrarlr#r7rrr r sLJ F E !!4,  244$00d**X3$3$j055$5n<,;rr N) sympy.corersympy.core.containersrsympy.tensor.arrayrsympy.core.sympifyrsympy.utilities.iterablesrr sympy.utilities.miscr collectionsr r r7rrr|s('$'7'#h;Uh;r