K iS`ddlmZddlmZddlmZddlmZGddeZGddeZ y ) isprime)PermutationGroup)DefaultPrinting) free_groupc(eZdZdZdZddZdZdZy)PolycyclicGroupTNcz||_||_||_|st|j|||_y||_y)a Parameters ========== pc_sequence : list A sequence of elements whose classes generate the cyclic factor groups of pc_series. pc_series : list A subnormal sequence of subgroups where each factor group is cyclic. relative_order : list The orders of factor groups of pc_series. collector : Collector By default, it is None. Collector class provides the polycyclic presentation with various other functionalities. N)pcgs pc_seriesrelative_order Collector collector)self pc_sequencer r rs c/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/combinatorics/pc_groups.py__init__zPolycyclicGroup.__init__ s7$  ",PY499iH_hc:td|jDS)Nc32K|]}t|ywNr).0orders r z1PolycyclicGroup.is_prime_order..$sCe75>Cs)allr rs ris_prime_orderzPolycyclicGroup.is_prime_order#sCt/B/BCCCrc,t|jSr)lenr rs rlengthzPolycyclicGroup.length&s499~rr)__name__ __module__ __qualname__is_group is_solvablerrr rrr r sHKi.Drr c`eZdZdZddZdZdZdZdZdZ d Z d Z d Z d Z d ZdZdZy)rz References ========== .. [1] Holt, D., Eick, B., O'Brien, E. "Handbook of Computational Group Theory" Section 8.1.3 Nc2||_||_||_|s&tdj t |dn||_t |jjDcic]\}}|| c}}|_|j|_ ycc}}w)a Most of the parameters for the Collector class are the same as for PolycyclicGroup. Others are described below. Parameters ========== free_group_ : tuple free_group_ provides the mapping of polycyclic generating sequence with the free group elements. pc_presentation : dict Provides the presentation of polycyclic groups with the help of power and conjugate relators. See Also ======== PolycyclicGroup zx:{}rN) r r r rformatr enumeratesymbolsindex pc_relatorspc_presentation)rr r r free_group_r.iss rrzCollector.__init__5s}, ",IT*V]]3t9%=>qAZe'01H1H'IJtq!adJ #//1Ks' Bct|sy|j}|j}|j}tt |D]-}||\}}|||s|dks||||dz kDs(||ffcStt |dz D]3}||\}}||dz\}} ||||kDs"| dkDrdnd} ||f|| ffcSy)a Returns the minimal uncollected subwords. Explanation =========== A word ``v`` defined on generators in ``X`` is a minimal uncollected subword of the word ``w`` if ``v`` is a subword of ``w`` and it has one of the following form * `v = {x_{i+1}}^{a_j}x_i` * `v = {x_{i+1}}^{a_j}{x_i}^{-1}` * `v = {x_i}^{a_j}` for `a_j` not in `\{1, \ldots, s-1\}`. Where, ``s`` is the power exponent of the corresponding generator. Examples ======== >>> from sympy.combinatorics.named_groups import SymmetricGroup >>> from sympy.combinatorics import free_group >>> G = SymmetricGroup(4) >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> F, x1, x2 = free_group("x1, x2") >>> word = x2**2*x1**7 >>> collector.minimal_uncollected_subword(word) ((x2, 2),) Nr) array_formr r,ranger) rwordarrayrer,r0s1e1s2e2es rminimal_uncollected_subwordz%Collector.minimal_uncollected_subwordRsF   s5z" $A1XFB%)}"q&BE"Iq,@R|#  $ s5z!|$ +A1XFB1Q3ZFBRy59$aARR2q'**  +rci}i}|jjD](\}}t|jdk(r|||<$|||<*||fS)a Separates the given relators of pc presentation in power and conjugate relations. Returns ======= (power_rel, conj_rel) Separates pc presentation into power and conjugate relations. Examples ======== >>> from sympy.combinatorics.named_groups import SymmetricGroup >>> G = SymmetricGroup(3) >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> power_rel, conj_rel = collector.relations() >>> power_rel {x0**2: (), x1**3: ()} >>> conj_rel {x0**-1*x1*x0: x1**2} See Also ======== pc_relators r3)r.itemsrr5)rpower_relatorsconjugate_relatorskeyvalues r relationszCollector.relationsse<..446 0JC3>>"a'&+s#*/"3'  0 111rcd}d}tt|t|z dzD]8}|j||t|z|k(s%|}|t|z}||fS||fS)a Returns the start and ending index of a given subword in a word. Parameters ========== word : FreeGroupElement word defined on free group elements for a polycyclic group. w : FreeGroupElement subword of a given word, whose starting and ending index to be computed. Returns ======= (i, j) A tuple containing starting and ending index of ``w`` in the given word. If not exists, (-1,-1) is returned. Examples ======== >>> from sympy.combinatorics.named_groups import SymmetricGroup >>> from sympy.combinatorics import free_group >>> G = SymmetricGroup(4) >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> F, x1, x2 = free_group("x1, x2") >>> word = x2**2*x1**7 >>> w = x2**2*x1 >>> collector.subword_index(word, w) (0, 3) >>> w = x1**7 >>> collector.subword_index(word, w) (2, 9) >>> w = x1**8 >>> collector.subword_index(word, w) (-1, -1) r4r3)r6rsubword)rr7wlowhighr0s r subword_indexzCollector.subword_indexs{Vs4yQ')* A||AqQx(A-QxDy   Dyrc|j}|dd}|dd}|df|df|dff}|jj|}|j|S)a Return a conjugate relation. Explanation =========== Given a word formed by two free group elements, the corresponding conjugate relation with those free group elements is formed and mapped with the collected word in the polycyclic presentation. Examples ======== >>> from sympy.combinatorics.named_groups import SymmetricGroup >>> from sympy.combinatorics import free_group >>> G = SymmetricGroup(3) >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> F, x0, x1 = free_group("x0, x1") >>> w = x1*x0 >>> collector.map_relation(w) x1**2 See Also ======== pc_presentation rr3r4)r5rdtyper.)rrIr8r:r<rDs r map_relationzCollector.map_relationsd>  1Xa[ 1Xa[Bx"a2q'*oo##C(##C((rc|j} |j|}|s |S|j||j|\}}|dk(rB|d\}}t |dk(r|j |j |}||z} || |zz } |dd|ff} |j| } |j| rE|j| j} | d\} }|dd| f| | |zff}|j|}n%| dk7r|dd| ff}|j|}nd}|j|j||}t |dk(ry|dddkDrn|d\}}|dff}|j|}|j|j|}|||zz}|j|}|j|||}nt |dk(r{|dddkrp|d\}}|dff}|j|}|j|j|}|dz||zz}|j|}|j|||}J)a Return the collected form of a word. Explanation =========== A word ``w`` is called collected, if `w = {x_{i_1}}^{a_1} * \ldots * {x_{i_r}}^{a_r}` with `i_1 < i_2< \ldots < i_r` and `a_j` is in `\{1, \ldots, {s_j}-1\}`. Otherwise w is uncollected. Parameters ========== word : FreeGroupElement An uncollected word. Returns ======= word A collected word of form `w = {x_{i_1}}^{a_1}, \ldots, {x_{i_r}}^{a_r}` with `i_1, i_2, \ldots, i_r` and `a_j \in \{1, \ldots, {s_j}-1\}`. Examples ======== >>> from sympy.combinatorics.named_groups import SymmetricGroup >>> from sympy.combinatorics.perm_groups import PermutationGroup >>> from sympy.combinatorics import free_group >>> G = SymmetricGroup(4) >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> F, x0, x1, x2, x3 = free_group("x0, x1, x2, x3") >>> word = x3*x2*x1*x0 >>> collected_word = collector.collected_word(word) >>> free_to_perm = {} >>> free_group = collector.free_group >>> for sym, gen in zip(free_group.symbols, collector.pcgs): ... free_to_perm[sym] = gen >>> G1 = PermutationGroup() >>> for w in word: ... sym = w[0] ... perm = free_to_perm[sym] ... G1 = PermutationGroup([perm] + G1.generators) >>> G2 = PermutationGroup() >>> for w in collected_word: ... sym = w[0] ... perm = free_to_perm[sym] ... G2 = PermutationGroup([perm] + G2.generators) The two are not identical, but they are equivalent: >>> G1.equals(G2), G1 == G2 (True, False) See Also ======== minimal_uncollected_subword r4rr3N) rr?rLrNrr r,r.r5eliminate_wordrOsubstituted_word)rr7rrIrJrKr:r;r9qrrD presentationsymexpword_r<r=s rcollected_wordzCollector.collected_wordsB__ 006AZ W**41A1A1A!1DEICbyqTFB1v{((B8"HqtG!Q}'&j&&s+'',#'#7#7#<#G#GL+AHCd1gq\C3<8E,J,,U3EAv"#A$q'1 0 0 0 0 7 $**+;:+;+;A+>F1v{qtAw{1B1g[%Z%%b)))*:**:*:1*=>5"9 ( ((/,,S$>Q11a11B1g[%Z%%b)))*:**:*:1*=>Buby(( ((/,,S$>]rc|j}|j}i}i}|j}t||jD]\}}|dz||dz<|||<|ddd}|j ddd}|ddd}g} t |D]L\} }|| } ||| z} || } | j|| zd}|j|j}|D] }|||z} |j|}|r|nd|| <||_ | j|t| dkDs| t| dz }||}tt| dz D]}|| |}|dz|z|z} |dz| |z|z}| j|d}|j|j}|D] }|||z} |j|}|r|nd|| <||_ O|S)aM Return the polycyclic presentation. Explanation =========== There are two types of relations used in polycyclic presentation. * Power relations : Power relators are of the form `x_i^{re_i}`, where `i \in \{0, \ldots, \mathrm{len(pcgs)}\}`, ``x`` represents polycyclic generator and ``re`` is the corresponding relative order. * Conjugate relations : Conjugate relators are of the form `x_j^-1x_ix_j`, where `j < i \in \{0, \ldots, \mathrm{len(pcgs)}\}`. Returns ======= A dictionary with power and conjugate relations as key and their collected form as corresponding values. Notes ===== Identity Permutation is mapped with empty ``()``. Examples ======== >>> from sympy.combinatorics.named_groups import SymmetricGroup >>> from sympy.combinatorics.permutations import Permutation >>> S = SymmetricGroup(49).sylow_subgroup(7) >>> der = S.derived_series() >>> G = der[len(der)-2] >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> pcgs = PcGroup.pcgs >>> len(pcgs) 6 >>> free_group = collector.free_group >>> pc_resentation = collector.pc_presentation >>> free_to_perm = {} >>> for s, g in zip(free_group.symbols, pcgs): ... free_to_perm[s] = g >>> for k, v in pc_resentation.items(): ... k_array = k.array_form ... if v != (): ... v_array = v.array_form ... lhs = Permutation() ... for gen in k_array: ... s = gen[0] ... e = gen[1] ... lhs = lhs*free_to_perm[s]**e ... if v == (): ... assert lhs.is_identity ... continue ... rhs = Permutation() ... for gen in v_array: ... s = gen[0] ... e = gen[1] ... rhs = rhs*free_to_perm[s]**e ... assert lhs == rhs r4NToriginalr&r3)rr r zip generatorsr r*generator_productreverseidentityrZr.appendrr6)rr rel_orderr- perm_to_freer genr1seriescollected_gensr0r9relationGlr7gconj conjugatorj conjugatedgenss rr-zCollector.pc_relatorssMF__ ''   yy$ 5 56 "FC$%rELb ! !L  "DbDz"%ddO o# 7FAs1B#C(",Hq A##CG#=A IIK&&D ,LO+ ,&&t,D,0DbK !#.D  ! !# &>"Q&%c.&9!&;<)$/ s>21457A!-nQ.?!@J)2~j8CH8N1$55d:D++DT+BAIIK%..D4#LO34 ..t4D48DbK)+6D(7+# 7Jrc|j}t}|jD]}t|g|jz}|j |d}|j i}t |j|jD]\}}|dz||dz<|||<|j}|D] }|||z} |j|} |j} dgt|z} | j} | D]} | d| | | d<| S)aJ Return the exponent vector of length equal to the length of polycyclic generating sequence. Explanation =========== For a given generator/element ``g`` of the polycyclic group, it can be represented as `g = {x_1}^{e_1}, \ldots, {x_n}^{e_n}`, where `x_i` represents polycyclic generators and ``n`` is the number of generators in the free_group equal to the length of pcgs. Parameters ========== element : Permutation Generator of a polycyclic group. Examples ======== >>> from sympy.combinatorics.named_groups import SymmetricGroup >>> from sympy.combinatorics.permutations import Permutation >>> G = SymmetricGroup(4) >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> pcgs = PcGroup.pcgs >>> collector.exponent_vector(G[0]) [1, 0, 0, 0] >>> exp = collector.exponent_vector(G[1]) >>> g = Permutation() >>> for i in range(len(exp)): ... g = g*pcgs[i]**exp[i] if exp[i] else g >>> assert g == G[1] References ========== .. [1] Holt, D., Eick, B., O'Brien, E. "Handbook of Computational Group Theory" Section 8.1.1, Definition 8.4 Tr\r4rr3) rrr r_r`rar^rbrZr,rr5) relementrrjrlrqrerWrIr7r, exp_vectorts rexponent_vectorzCollector.exponent_vectors)Z__   5A !q||!34A 5""7t"<  *//; "FC"%r'LB !LO "    "A,q/!A """1% SZ(  +A&'dJuQqT{ # +rc|j|}tdt|Dt|jdzS)a Return the depth of a given element. Explanation =========== The depth of a given element ``g`` is defined by `\mathrm{dep}[g] = i` if `e_1 = e_2 = \ldots = e_{i-1} = 0` and `e_i != 0`, where ``e`` represents the exponent-vector. Examples ======== >>> from sympy.combinatorics.named_groups import SymmetricGroup >>> G = SymmetricGroup(3) >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> collector.depth(G[0]) 2 >>> collector.depth(G[1]) 1 References ========== .. [1] Holt, D., Eick, B., O'Brien, E. "Handbook of Computational Group Theory" Section 8.1.1, Definition 8.5 c32K|]\}}|s |dzyw)r3Nr&)rr0xs rrz"Collector.depth..as@TQaQqS@s  r3)rvnextr*rr )rrsrts rdepthzCollector.depthAs:>))'2 @Yz%:@#dii.QRBRSSrc|j|}|j|}|t|jdzk7r||dz Sy)a  Return the leading non-zero exponent. Explanation =========== The leading exponent for a given element `g` is defined by `\mathrm{leading\_exponent}[g]` `= e_i`, if `\mathrm{depth}[g] = i`. Examples ======== >>> from sympy.combinatorics.named_groups import SymmetricGroup >>> G = SymmetricGroup(3) >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> collector.leading_exponent(G[1]) 1 r3N)rvr{rr )rrsrtr{s rleading_exponentzCollector.leading_exponentcsI*))'2  7# C N1$ $eAg& &rct|}|j|}|t|jkr||dz dk7r||dz }|j||j|dzz}||j|dz z}|| z|z}|j|}|t|jkr ||dz dk7r|S)Nr3r4)r{rr r}r )rzrlhdkr>s r_siftzCollector._sift~s  JJqM#dii. QqsVq[!A#A%%a($*?*?*BR)GGAD''!,,AA2aA 1 A #dii. QqsVq[ rc|dgt|jz}|}|r|jd}|j||}|j |}|t|jkr5|D](}|dk7s |j |dz|dzz|z|z*|||dz <|r|Dcgc] }|dk7s | }}|Scc}w)a8 Parameters ========== gens : list A list of generators on which polycyclic subgroup is to be defined. Examples ======== >>> from sympy.combinatorics.named_groups import SymmetricGroup >>> S = SymmetricGroup(8) >>> G = S.sylow_subgroup(2) >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> gens = [G[0], G[1]] >>> ipcgs = collector.induced_pcgs(gens) >>> [gen.order() for gen in ipcgs] [2, 2, 2] >>> G = S.sylow_subgroup(3) >>> PcGroup = G.polycyclic_group() >>> collector = PcGroup.collector >>> gens = [G[0], G[1]] >>> ipcgs = collector.induced_pcgs(gens) >>> [gen.order() for gen in ipcgs] [3] r3rr4)rr poprr{rc)rrqrrjrlrrrfs r induced_pcgszCollector.induced_pcgss>CDII  aA 1a A 1 A3tyy>!6CaxBsBwq!456!A# *SS * * +s & B91B9c~dgt|z}|}|j|}t|D]\}}|j||k(s|j||j|z}||j|dz z}|| z|z}|||<|j|}|j||k(rl|dk(r|Sy)z> Return the exponent vector for induced pcgs. rr3F)rr{r*r}r ) ripcgsrlr>rrr0rffs rconstructive_membership_testz&Collector.constructive_membership_testsCE N  JJqM& "FAs**S/Q&))!,T-B-B3-GG++AaC001"IaK!JJqM **S/Q& " 6Hr)NN)r!r"r#__doc__rr?rFrLrOrZr-rvr{r}rrrr&rrrr*sU2:8t%2N2h$)NrjwrCJ TD6 +ZrrN) sympy.ntheory.primetestrsympy.combinatorics.perm_groupsrsympy.printing.defaultsrsympy.combinatorics.free_groupsrr rr&rrrs,+<36 o F\ \ r