K i<UddlmZddlmZddlmZddlmZmZ ddl m Z ddl m Z ddlmZddlmZmZdd lmZdd lmZed Zed Zed ZdZiZded<Gdde ZGdde e eZdZ dZ!y)) annotations)S)Expr)Symbolsymbols) CantSympify)DefaultPrinting)public)flatten is_sequence)pollute)as_intcJt|}|ft|jzS)aConstruct a free group returning ``(FreeGroup, (f_0, f_1, ..., f_(n-1))``. Parameters ========== symbols : str, Symbol/Expr or sequence of str, Symbol/Expr (may be empty) Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y, z = free_group("x, y, z") >>> F >>> x**2*y**-1 x**2*y**-1 >>> type(_) ) FreeGrouptuple generatorsr _free_groups e/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/combinatorics/free_groups.py free_grouprs&,G$K >E+"8"89 99c4t|}||jfS)aConstruct a free group returning ``(FreeGroup, (f_0, f_1, ..., f_(n-1)))``. Parameters ========== symbols : str, Symbol/Expr or sequence of str, Symbol/Expr (may be empty) Examples ======== >>> from sympy.combinatorics.free_groups import xfree_group >>> F, (x, y, z) = xfree_group("x, y, z") >>> F >>> y**2*x**-2*z**-1 y**2*x**-2*z**-1 >>> type(_) )rrrs r xfree_groupr's,G$K // 00rct|}t|jDcgc]}|jc}|j|Scc}w)aConstruct a free group and inject ``f_0, f_1, ..., f_(n-1)`` as symbols into the global namespace. Parameters ========== symbols : str, Symbol/Expr or sequence of str, Symbol/Expr (may be empty) Examples ======== >>> from sympy.combinatorics.free_groups import vfree_group >>> vfree_group("x, y, z") >>> x**2*y**-2*z # noqa: F821 x**2*y**-2*z >>> type(_) )rr rnamer)rrsyms r vfree_groupr@s>,G$K !4!4 5#SXX 5{7M7MN  6sAc|syt|tr t|dSt|ttfr|fSt |r1t d|Dr t|St d|Dr|Std)NT)seqc3<K|]}t|tywN) isinstancestr.0ss r z!_parse_symbols..cs3az!S!3c3<K|]}t|tywr")r#rr%s rr(z!_parse_symbols..es6At$6r)zjThe type of `symbols` must be one of the following: a str, Symbol/Expr or a sequence of one of these types)r#r$_symbolsrFreeGroupElementr all ValueErrorrs r_parse_symbolsr0[s} '3T** Gd$45 6z W  373 3G$ $ 6g6 6N * ++rzdict[int, FreeGroup]_free_group_cacheceZdZUdZdZdZdZdZgZde d<dZ dZ dZ d Z dd Zd Zd ZdZdZeZdZdZdZdZedZedZedZedZdZdZy )ra Free group with finite or infinite number of generators. Its input API is that of a str, Symbol/Expr or a sequence of one of these types (which may be empty) See Also ======== sympy.polys.rings.PolyRing References ========== .. [1] https://www.gap-system.org/Manuals/doc/ref/chap37.html .. [2] https://en.wikipedia.org/wiki/Free_group TFz list[Expr]relatorscVtt|}t|}t|j||f}t j |}|tj|}||_ ||_ tdtfd|i|_ ||_|j|_t#|j |_t'|j|j D]<\}}t)|t*s|j,}t/||s0t1|||>|t |<|S)Nr,group)rr0lenhash__name__r1getobject__new___hash_ranktyper,dtyper _generatorsrset _gens_setzipr#rrhasattrsetattr)clsrrankr<objsymbol generatorrs rr;zFreeGroup.__new__sw/07|cllGT23##E* ;..%CCICI/2B1DwPSnUCI!CK __.CN/CM%(cnn%E 6! ff-!;;DsD)T95  6 (+ e $ rc|jfS)zdReturn a tuple of arguments that must be passed to __new__ in order to support pickling this object.r/selfs r__getnewargs__zFreeGroup.__getnewargs__s rcyr"rrLs r __getstate__zFreeGroup.__getstate__srcg}|jD]'}|dff}|j|j|)t|S)zReturns the generators of the FreeGroup. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y, z = free_group("x, y, z") >>> F.generators (x, y, z) )rappendr?r)r5gensrelms rr@zFreeGroup._generatorssH== *C8+C KK C( ) *T{rNc@|j|xs |jSr") __class__r)rMrs rclonezFreeGroup.clones~~g566rcFt|tsy|j}||k(S)z/Return True if ``i`` is contained in FreeGroup.Fr#r,r5)rMir5s r __contains__zFreeGroup.__contains__s#!-.u}rc|jSr")r<rLs r__hash__zFreeGroup.__hash__s zzrc|jSr"rGrLs r__len__zFreeGroup.__len__s yyrc|jdkDrd|jz}|Sd}|j}|t|dzz }|S)Nzz)rGrr$)rMstr_formrTs r__str__zFreeGroup.__str__sI 99r>8499DH 8H??D D C 'HrcD|j|}|j|S)Nr/)rrX)rMindexrs r __getitem__zFreeGroup.__getitem__s!,,u%zz'z**rc ||uS)z@No ``FreeGroup`` is equal to any "other" ``FreeGroup``. rrMothers r__eq__zFreeGroup.__eq__su}rct||jr|jj|St d|d|)aReturn the index of the generator `gen` from ``(f_0, ..., f_(n-1))``. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> F.index(y) 1 >>> F.index(x) 0 z#expected a generator of Free Group z, got )r#r?rrhr.rMgens rrhzFreeGroup.indexs9 c4:: &??((- -PTVYZ[ [rc`|jdk(rtjStjS)aReturn the order of the free group. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> F.order() oo >>> free_group("")[0].order() 1 r)rGrOneInfinityrLs rorderzFreeGroup.orders" 99>55L:: rcP|jdk(r |jhStd)z Return the elements of the free group. Examples ======== >>> from sympy.combinatorics import free_group >>> (z,) = free_group("") >>> z.elements {} rzDGroup contains infinitely many elements, hence cannot be represented)rGidentityr.rLs relementszFreeGroup.elements s- 99>MM? "<= =rc|jS)a In group theory, the `rank` of a group `G`, denoted `G.rank`, can refer to the smallest cardinality of a generating set for G, that is \operatorname{rank}(G)=\min\{ |X|: X\subseteq G, \left\langle X\right\rangle =G\}. )r=rLs rrGzFreeGroup.rankszzrc|jdvS)zReturns if the group is Abelian. Examples ======== >>> from sympy.combinatorics import free_group >>> f, x, y, z = free_group("x y z") >>> f.is_abelian False )rrRr`rLs r is_abelianzFreeGroup.is_abelian*syyF""rc"|jS)z+Returns the identity element of free group.)r?rLs rrvzFreeGroup.identity9szz|rcFt|tsy||jk7ryy)aiTests if Free Group element ``g`` belong to self, ``G``. In mathematical terms any linear combination of generators of a Free Group is contained in it. Examples ======== >>> from sympy.combinatorics import free_group >>> f, x, y, z = free_group("x y z") >>> f.contains(x**3*y**2) True FTrZ)rMgs rcontainszFreeGroup.contains>s#!-. QWW_rc|jhS)z,Returns the center of the free group `self`.)rvrLs rcenterzFreeGroup.centerTs rr")r8 __module__ __qualname____doc__is_associativeis_group is_FreeGroupis_PermutationGroupr3__annotations__r;rNrPr@rXr\r^rarf__repr__rirmrhrtpropertyrwrGrzrvr~rrrrrrrs$NHLHj2$7H+ \&(==(   # #,rrcveZdZdZdZdZdZdZdZdZ e dZ e d Z e d Z d Zd Ze d Ze dZdZdZeZdZdZdZdZdZdZdZdZd4dZd5dZdZdZ dZ!dZ"dZ#d Z$d!Z%d"Z&d6d#Z'd7d$Z(d%Z)d&Z*d'Z+d(Z,d)Z-d*Z.d+Z/d,Z0d-Z1d.Z2d/Z3d0Z4d1Z5d8d2Z6d3Z7y)9r,zUsed to create elements of FreeGroup. It cannot be used directly to create a free group element. It is called by the `dtype` method of the `FreeGroup` class. rTc$|j|Sr")rW)rMinits rnewzFreeGroupElement.newgs~~d##rNc|j}|0t|jtt |fx|_}|Sr")r<r7r5 frozensetr)rMr<s rr^zFreeGroupElement.__hash__ls8  =!%tzz9U4[3I&J!K KDJ rc$|j|Sr")rrLs rcopyzFreeGroupElement.copyrsxx~rc|j Sr" array_formrLs r is_identityzFreeGroupElement.is_identityus??""rct|S)a SymPy provides two different internal kinds of representation of associative words. The first one is called the `array_form` which is a tuple containing `tuples` as its elements, where the size of each tuple is two. At the first position the tuple contains the `symbol-generator`, while at the second position of tuple contains the exponent of that generator at the position. Since elements (i.e. words) do not commute, the indexing of tuple makes that property to stay. The structure in ``array_form`` of ``FreeGroupElement`` is of form: ``( ( symbol_of_gen, exponent ), ( , ), ... ( , ) )`` Examples ======== >>> from sympy.combinatorics import free_group >>> f, x, y, z = free_group("x y z") >>> (x*z).array_form ((x, 1), (z, 1)) >>> (x**2*z*y*x**2).array_form ((x, 2), (z, 1), (y, 1), (x, 2)) See Also ======== letter_repr )rrLs rrzFreeGroupElement.array_formys@T{rc tt|jDcgc]\}}|dkDr|f|zn| f| zc}}Scc}}w)a The letter representation of a ``FreeGroupElement`` is a tuple of generator symbols, with each entry corresponding to a group generator. Inverses of the generators are represented by negative generator symbols. Examples ======== >>> from sympy.combinatorics import free_group >>> f, a, b, c, d = free_group("a b c d") >>> (a**3).letter_form (a, a, a) >>> (a**2*d**-2*a*b**-4).letter_form (a, a, -d, -d, a, -b, -b, -b, -b) >>> (a**-2*b**3*d).letter_form (-a, -a, b, b, b, d) See Also ======== array_form rrr r)rMr[js r letter_formzFreeGroupElement.letter_formsV4W $11)*Aqd1fQB51":=123 31sAc|j}|j|}|jr|j|dffS|j| dffS)NrRr5r is_Symbolr?)rMr[r5rs rrizFreeGroupElement.__getitem__sN    Q  ;;;;Ay) );;!R{+ +rct|dk7r t|jj|jdS)NrRr)r6r.rrhros rrhzFreeGroupElement.indexs5 s8q=,   ''(:;;rc|j}|j}|Dcgc]7}|jr|j|dffn|j| dff9c}Scc}w)z rRrr)rMr5rrUs rletter_form_elmz FreeGroupElement.letter_form_elmsf    :;=36,/== c!WJ'[[C4)./= ==stt|jS)zKThis is called the External Representation of ``FreeGroupElement`` rrLs rext_repzFreeGroupElement.ext_repsWT__-..rc||jddt|jDcgc]}|d c}vScc}w)Nr)rr)rMrprs rr\zFreeGroupElement.__contains__s6~~a #uDOO-Lqad-L'MMM-Ls 9 c|jryd}|j}tt|D]}|t|dz k(rJ||ddk(r|t ||dz }4|t ||ddzt ||dzz }^||ddk(r|t ||ddzz }|t ||ddzt ||dzdzz }|S)Nz rRrz***)rrranger6r$)rMrerr[s rrfzFreeGroupElement.__str__s$   __ s:' GAC Oa''a=#q(JqM!$4 55HJqM!$4 5$(!)+.z!}Q/?+@!AAHa=#q(JqM!$4 5 ;;HJqM!$4 5$(!)+.z!}Q/?+@!ACF!GGH Grct|}|jj}|dk(r|S|dkr| }|j}n|} |dzr||z}|dz}|s |S||z})NrrR)rr5rvinverse)rMnresultxs r__pow__zFreeGroupElement.__pow__s{ 1I$$ 6M q5A AA1u!  !GA  FA rcP|j}t||js td|jr|S|jr|St |j |j z}t|t|j dz |jt|S)aUReturns the product of elements belonging to the same ``FreeGroup``. Examples ======== >>> from sympy.combinatorics import free_group >>> f, x, y, z = free_group("x y z") >>> x*y**2*y**-4 x*y**-2 >>> z*y**-2 z*y**-2 >>> x**2*y*y**-1*x**-2 ;only FreeGroup elements of same FreeGroup can be multipliedrR) r5r#r? TypeErrorrlistr zero_mul_simpr6r)rMrlr5rs r__mul__zFreeGroupElement.__mul__s  %-$% %   L   K 5#3#33 4aT__-12{{58$$rc|j}t||js td||j zSNrr5r#r?rrrMrlr5s r __truediv__zFreeGroupElement.__truediv__s< %-$% %U]]_%%rc|j}t||js td||j zSrrrs r __rtruediv__zFreeGroupElement.__rtruediv__$s< %-$% %dlln%%rctSr")NotImplementedrks r__add__zFreeGroupElement.__add__+src|j}t|jdddDcgc] \}}|| f c}}}|j|Scc}}w)a& Returns the inverse of a ``FreeGroupElement`` element Examples ======== >>> from sympy.combinatorics import free_group >>> f, x, y, z = free_group("x y z") >>> x.inverse() x**-1 >>> (x*y).inverse() y**-1*x**-1 Nr)r5rrr?)rMr5r[rrs rrzFreeGroupElement.inverse.sL  ttt'<=tq!Ar7= >{{1~>sA cZ|jrtjStjS)zFind the order of a ``FreeGroupElement``. Examples ======== >>> from sympy.combinatorics import free_group >>> f, x, y = free_group("x y") >>> (x**2*y*y**-1*x**-2).order() 1 )rrrrrsrLs rrtzFreeGroupElement.orderAs    55L:: rc|j}t||js td|j |j z|z|zS)zO Return the commutator of `self` and `x`: ``~x*~self*x*self`` z@commutator of only FreeGroupElement of the same FreeGroup exists)r5r#r?r.rrs r commutatorzFreeGroupElement.commutatorRsP  %-'( (<<>%--/1$6u< >> from sympy.combinatorics import free_group >>> f, x, y = free_group("x y") >>> w = x**5*y*x**2*y**-4*x >>> w.eliminate_word( x, x**2 ) x**10*y*x**4*y**-4*x**2 >>> w.eliminate_word( x, y**-1 ) y**-11 >>> w.eliminate_word(x**5) y*x**2*y**-4*x >>> w.eliminate_word(x*y, y) x**4*y*x**2*y**-4*x See Also ======== substituted_word rFrRrTr)r5rvis_independentr6 subword_indexr.subwordr) rMrpbyrrwordlr[ks rrzFreeGroupElement.eliminate_wordxs): :$$B   s #sbyK $;I 7b=D H ""3'AA||Aq!"a%' QqS#d)(D(S(STWY[(\\ &&sBT7&K KK   &&sBw/     s6C DC*)D* C:5D9C::D?Dc&td|DS)a^ For an associative word `self`, returns the number of letters in it. Examples ======== >>> from sympy.combinatorics import free_group >>> f, a, b = free_group("a b") >>> w = a**5*b*a**2*b**-4*a >>> len(w) 13 >>> len(a**17) 17 >>> len(w**0) 0 c38K|]\}}t|ywr"abs)r&r[rs rr(z+FreeGroupElement.__len__..s-fq!3q6-s)sumrLs rrazFreeGroupElement.__len__s$----rct|j}t||jsytj ||S)a Two associative words are equal if they are words over the same alphabet and if they are sequences of the same letters. This is equivalent to saying that the external representations of the words are equal. There is no "universal" empty word, every alphabet has its own empty word. Examples ======== >>> from sympy.combinatorics import free_group >>> f, swapnil0, swapnil1 = free_group("swapnil0 swapnil1") >>> f >>> g, swap0, swap1 = free_group("swap0 swap1") >>> g >>> swapnil0 == swapnil1 False >>> swapnil0*swapnil1 == swapnil1/swapnil1*swapnil0*swapnil1 True >>> swapnil0*swapnil1 == swapnil1*swapnil0 False >>> swapnil1**0 == swap0**0 False F)r5r#r?rrmrs rrmzFreeGroupElement.__eq__s/< %-||D%((rc|j}t||js tdt |}t |}||kry||kDryt |D]}||j d}||j d}|jj|d}|jj|d} || kry|| kDry|d|dkry|d|dkDsyy)a, The ordering of associative words is defined by length and lexicography (this ordering is called short-lex ordering), that is, shorter words are smaller than longer words, and words of the same length are compared w.r.t. the lexicographical ordering induced by the ordering of generators. Generators are sorted according to the order in which they were created. If the generators are invertible then each generator `g` is larger than its inverse `g^{-1}`, and `g^{-1}` is larger than every generator that is smaller than `g`. Examples ======== >>> from sympy.combinatorics import free_group >>> f, a, b = free_group("a b") >>> b < a False >>> a < a.inverse() False 9only FreeGroup elements of same FreeGroup can be comparedTFrrR) r5r#r?rr6rrrrh) rMrlr5rmr[abpqs r__lt__zFreeGroupElement.__lt__s, %-+, , I J q5 Uq AQ""1%Aa##A&A ##AaD)A ##AaD)A1uQ1!1! rc||k(xs||kSr"rrks r__le__zFreeGroupElement.__le__s -.rch|j}t||js td||k S)a Examples ======== >>> from sympy.combinatorics import free_group >>> f, x, y, z = free_group("x y z") >>> y**2 > x**2 True >>> y*z > z*y False >>> x > x.inverse() True r)r5r#r?rrs r__gt__zFreeGroupElement.__gt__s:  %-+, ,5=  rc||k Sr"rrks r__ge__zFreeGroupElement.__ge__3s%<rct|dk7r td|jddtfd|jDzS)a For an associative word `self` and a generator or inverse of generator `gen`, ``exponent_sum`` returns the number of times `gen` appears in `self` minus the number of times its inverse appears in `self`. If neither `gen` nor its inverse occur in `self` then 0 is returned. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> w = x**2*y**3 >>> w.exponent_sum(x) 2 >>> w.exponent_sum(x**-1) -2 >>> w = x**2*y**4*x**-3 >>> w.exponent_sum(x) -1 See Also ======== generator_count rRz1gen must be a generator or inverse of a generatorrc3@K|]}|ddk(s|dywrrRNrr&r[r's rr(z0FreeGroupElement.exponent_sum..Ts#F11!Fs )r6r.rrrMrpr's @r exponent_sumzFreeGroupElement.exponent_sum6sH6 s8q=PQ Q NN1 tCFdooFFFFrct|dk7s|jdddkr td|jddtfd|jDzS)a For an associative word `self` and a generator `gen`, ``generator_count`` returns the multiplicity of generator `gen` in `self`. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> w = x**2*y**3 >>> w.generator_count(x) 2 >>> w = x**2*y**4*x**-3 >>> w.generator_count(x) 5 See Also ======== exponent_sum rRrzgen must be a generatorc3RK|]}|ddk(st|d ywrrrs rr(z3FreeGroupElement.generator_count..qs'KaadadlAaD Ks'')r6rr.rrs @rgenerator_countz FreeGroupElement.generator_countVs]0 s8q=CNN1-a01467 7 NN1 tCK4??KKKKrc|j}|s!t|d}tt||}|dks|t|kDr t d||kr |j S|j ||}t||}|j|S)a For an associative word `self` and two positive integers `from_i` and `to_j`, `subword` returns the subword of `self` that begins at position `from_i` and ends at `to_j - 1`, indexing is done with origin 0. Examples ======== >>> from sympy.combinatorics import free_group >>> f, a, b = free_group("a b") >>> w = a**5*b*a**2*b**-4*a >>> w.subword(2, 6) a**3*b rzT`from_i`, `to_j` must be positive and no greater than the length of associative word) r5maxminr6r.rvrletter_form_to_array_formr?)rMfrom_ito_jstrictr5rrs rrzFreeGroupElement.subwordss  ^Fs4y$'D A:D )56 6 6>>> !**648K2;FJ;;z* *rct|}|j}|j}d}t|t||z dzD]}||||z|k(s|}n||Std)a Find the index of `word` in `self`. Examples ======== >>> from sympy.combinatorics import free_group >>> f, a, b = free_group("a b") >>> w = a**2*b*a*b**3 >>> w.subword_index(a*b*a*b) 1 NrRz'The given word is not a subword of self)r6rrr.)rMrstartrself_lfword_lfrhr[s rrzFreeGroupElement.subword_indexs~ I""""uS\!^A-. Aq1~(   LFG Grc |j|duS#t$rYnwxYw |j|dzduS#t$rYywxYw)a Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> (x**4*y**-3).is_dependent(x**4*y**-2) True >>> (x**2*y**-1).is_dependent(x*y) False >>> (x*y**2*x*y**2).is_dependent(x*y**2) True >>> (x**12).is_dependent(x**-4) True See Also ======== is_independent NrF)rr.rMrs r is_dependentzFreeGroupElement.is_dependents`, %%d+47 7    %%dBh/t; ;  s !!; AAc&|j| S)zC See Also ======== is_dependent )rrs rrzFreeGroupElement.is_independents$$T***rc|j}|jDchc]}|j|ddff}}|Scc}w)a  Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y, z = free_group("x, y, z") >>> (x**2*y**-1).contains_generators() {x, y} >>> (x**3*z).contains_generators() {x, z} rrR)r5rr?)rMr5syllablerTs rcontains_generatorsz$FreeGroupElement.contains_generatorssD AEQX hqk1-/0QQ Rs=c2|j}t|}|j}t||z }||k\r|||zz}|||zz}||z }|||}t||z dz } ||| z|d||z |z|| zz zz }t ||}|j |S)NrR)r5r6rintrr?) rMrrr5rrperiod1diffrperiod2s rcyclic_subwordzFreeGroupElement.cyclic_subwords  I&& fQh- Q; ai F AgI Df}64(d1f+/ G#k2J46&=73J&KKK(u5{{4  rc tt|Dchc] }|j||t|z"c}Scc}w)aReturns a words which are cyclic to the word `self`. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> w = x*y*x*y*x >>> w.cyclic_conjugates() {x*y*x**2*y, x**2*y*x*y, y*x*y*x**2, y*x**2*y*x, x*y*x*y*x} >>> s = x*y*x**2*y*x >>> s.cyclic_conjugates() {x**2*y*x**2*y, y*x**2*y*x**2, x*y*x**2*y*x} References ========== .. [1] https://planetmath.org/cyclicpermutation )rr6r rMr[s rcyclic_conjugatesz"FreeGroupElement.cyclic_conjugatess7*>C3t9=MN##AqT{3NNNs%?cjt|}t|}||k7ry|j}|j}|j}|j}djt t |}djt t |} t|t| k7ry|| dz| zvS)a Checks whether words ``self``, ``w`` are cyclic conjugates. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> w1 = x**2*y**5 >>> w2 = x*y**5*x >>> w1.is_cyclic_conjugate(w2) True >>> w3 = x**-1*y**5*x**-1 >>> w3.is_cyclic_conjugate(w2) False F )r6identity_cyclic_reductionrjoinmapr$) rMwl1l2w1w2letter1letter2str1str2s ris_cyclic_conjugatez$FreeGroupElement.is_cyclic_conjugate s$Y V 8  + + -  ( ( *....xxC)*xxC)* t9D !tczD(((rc,t|jS)a5Returns the number of syllables of the associative word `self`. Examples ======== >>> from sympy.combinatorics import free_group >>> f, swapnil0, swapnil1 = free_group("swapnil0 swapnil1") >>> (swapnil1**3*swapnil0*swapnil1**-1).number_syllables() 3 )r6rrLs rnumber_syllablesz!FreeGroupElement.number_syllables.s4??##rc&|j|dS)a< Returns the exponent of the `i`-th syllable of the associative word `self`. Examples ======== >>> from sympy.combinatorics import free_group >>> f, a, b = free_group("a b") >>> w = a**5*b*a**2*b**-4*a >>> w.exponent_syllable( 2 ) 2 rRrrs rexponent_syllablez"FreeGroupElement.exponent_syllable<q!!$$rc&|j|dS)a[ Returns the symbol of the generator that is involved in the i-th syllable of the associative word `self`. Examples ======== >>> from sympy.combinatorics import free_group >>> f, a, b = free_group("a b") >>> w = a**5*b*a**2*b**-4*a >>> w.generator_syllable( 3 ) b rrrs rgenerator_syllablez#FreeGroupElement.generator_syllableMr#rct|trt|ts td|j}||kr |jSt |j ||}|j|S)a `sub_syllables` returns the subword of the associative word `self` that consists of syllables from positions `from_to` to `to_j`, where `from_to` and `to_j` must be positive integers and indexing is done with origin 0. Examples ======== >>> from sympy.combinatorics import free_group >>> f, a, b = free_group("a, b") >>> w = a**5*b*a**2*b**-4*a >>> w.sub_syllables(1, 2) b >>> w.sub_syllables(3, 3) z!both arguments should be integers)r#rr.r5rvrrr?)rMrrr5rs r sub_syllableszFreeGroupElement.sub_syllables^s`&&#&js.C@A A  6>>> !doofd34A;;q> !rct|}||k\s ||kDs||kDr td|dk(r||k(r|S|dk(r||j||zS||k(r|jd||zS|jd||z|j||zS)a  Returns the associative word obtained by replacing the subword of `self` that begins at position `from_i` and ends at position `to_j - 1` by the associative word `by`. `from_i` and `to_j` must be positive integers, indexing is done with origin 0. In other words, `w.substituted_word(w, from_i, to_j, by)` is the product of the three words: `w.subword(0, from_i)`, `by`, and `w.subword(to_j len(w))`. See Also ======== eliminate_word zvalues should be within boundsr)r6r.r)rMrrrlws rsubstituted_wordz!FreeGroupElement.substituted_wordzs Y T>Vb[D2I=> > Q;42:I q[dll4,, , RZ<<6*2- -<<6*2-dll4.DD Drc$|sy|d|ddzk7S)a Returns whether the word is cyclically reduced or not. A word is cyclically reduced if by forming the cycle of the word, the word is not reduced, i.e a word w = `a_1 ... a_n` is called cyclically reduced if `a_1 \ne a_n^{-1}`. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> (x**2*y**-1*x**-1).is_cyclically_reduced() False >>> (y*x**2*y**2).is_cyclically_reduced() True TrrrrLs ris_cyclically_reducedz&FreeGroupElement.is_cyclically_reduceds!"Aw$r(B,&&rc|j}|j}|js|jd}|jd}||z}|dk(r!|jd|j dz }n8|j d||zff|jd|j dz z}|j|}|js|S)aReturn a unique cyclically reduced version of the word. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> (x**2*y**2*x**-1).identity_cyclic_reduction() x*y**2 >>> (x**-3*y**-1*x**5).identity_cyclic_reduction() x**2*y**-1 References ========== .. [1] https://planetmath.org/cyclicallyreduced rrrR)rr5r,r"rr r%r?)rMrr5exp1exp2rreps rrz*FreeGroupElement.identity_cyclic_reductions&yy{ ,,.))!,D))"-Dt AAvooa)>)>)@1)DE//2D4K@B4+@+@+BQ+FGH;;s#D,,. rc|j}|jj}|jst |j d}t |j d}t ||}|dt |z}|dt |z}|dz|z|dzz}||z}|js|r||fS|S)a/Return a cyclically reduced version of the word. Unlike `identity_cyclic_reduction`, this will not cyclically permute the reduced word - just remove the "unreduced" bits on either side of it. Compare the examples with those of `identity_cyclic_reduction`. When `removed` is `True`, return a tuple `(word, r)` where self `r` is such that before the reduction the word was either `r*word*r**-1`. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> (x**2*y**2*x**-1).cyclic_reduction() x*y**2 >>> (x**-3*y**-1*x**5).cyclic_reduction() y**-1*x**2 >>> (x**-3*y**-1*x**5).cyclic_reduction(removed=True) (y**-1*x**2, x**-3) rr)rr5rvr,rr"r) rMremovedrr}r.r/exprends rcyclic_reductionz!FreeGroupElement.cyclic_reductions0yy{ JJ  ,,.t--a01Dt--b12DdD/CGSX%Er(CH$C"9T>#r')D%A,,. 7N rc|jryt|}|dk(r/|j}||vxs|dz|v}t|dk(xr|S|jd\}}|js,|jd\}}||k(r|j |Syt||kst||zry|j d|}||k(s|dz|k(r,|j |t|} | j |Sy)a; Check if `self == other**n` for some integer n. Examples ======== >>> from sympy.combinatorics import free_group >>> F, x, y = free_group("x, y") >>> ((x*y)**2).power_of(x*y) True >>> (x**-3*y**-2*x**3).power_of(x**-3*y*x**3) True TrRr)r2Fr)rr6rr5power_ofr) rMrlrrTr'reducedr1r2prefixrests rr7zFreeGroupElement.power_ofs     J 6++-D 2d!2At9>'a ' ++D+9 ~~..t. +" !O.)B $%"%""8E@'*B$L*rr,c@t|dd}g}d}|j}tt|D]}|t|dz k(r||||dz k(r>|| |vr|j || | f|cS|j |||f|cS|| |vr|j || df|cS|j ||df|cS||||dzk(r|dz }|| |vr|j || | fn|j |||fd}y)a` This method converts a list given with possible repetitions of elements in it. It returns a new list such that repetitions of consecutive elements is removed and replace with a tuple element of size two such that the first index contains `value` and the second index contains the number of consecutive repetitions of `value`. NrRr)rrrr6rS)rr5r new_arrayrrr[s rrr#s] Z]AI AmmG 3q6] A ?tqQxqTEg%$$qteaR[1  $$adAY/   qTEg%$$qteR[1 $$adAY/  qTQq1uX  FA1'!  1Q4%!-  !A$+A)rc0|dk\r|t|dz kr||d||dzdk(rj||d||dzdz}||d}||f||<||dz=||ddk(r||=|dz}|dk\r(|t|dz kr||d||dzdk(rgyyyyyy)z"Used to combine two reduced words.rrRN)r6)rrhr3bases rrrGs !)A *qx{a l1o/MhqkAeaiLO+x{#;% eaiL U8A;! % QJE !)A *qx{a l1o/M*)/M*)rN)" __future__r sympy.corersympy.core.exprrsympy.core.symbolrrr+sympy.core.sympifyrsympy.printing.defaultsr sympy.utilitiesr sympy.utilities.iterablesr r sympy.utilities.magicr sympy.utilities.miscrrrrr0r1rrrr,rrrrrrMs" 9*3":)'::01104+*+-',ddXB{OUBJ!H r