K iIddlZddlmZmZmZddlmZddlmZddl m Z ddl m Z ddl mZGdd Zdd Zd Zd Zd ZddZdZy)N)FpGroup FpSubgroupsimplify_presentation) FreeGroup)PermutationGroup)igcd)totient)ScjeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZy)GroupHomomorphismz A class representing group homomorphisms. Instantiate using `homomorphism()`. References ========== .. [1] Holt, D., Eick, B. and O'Brien, E. (2005). Handbook of computational group theory. cX||_||_||_d|_d|_d|_yN)domaincodomainimages _inverses_kernel_image)selfrrrs g/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/combinatorics/homomorphisms.py__init__zGroupHomomorphism.__init__s,      c:|j}i}t|jjD](}|j|}||vr|jr$|||<*t |j tr |j}n |j}|D]}||vs |jr|jj}t |j tr|j|ddd}n|}|D]} | |vr ||| z}||| dzdzz}|||<|S)z Return a dictionary with `{gen: inverse}` where `gen` is a rewriting generator of `codomain` (e.g. strong generator for permutation groups) and `inverse` is an element of its preimage N) imagelistrkeys is_identity isinstancerr strong_gens generatorsridentity_strong_gens_slp) rrinverseskvgensgwpartsss r_invszGroupHomomorphism._invss' dkk&&() A AAM}}  dmm%5 6$$D##D AH}  $$A$--)9:..q1$B$7 .=(1+ A(1b5/2--A  . HQK rcddlm}ddlm}t |||frt |j t r|j j|}|j|j|_|j}|jj}t |j tr|j|ddd}n|}tt!|D]M}||}|j"r||jvr||j|z}6||j|dzdzz}O|St |t$r|D cgc]} |j'| c} Sycc} w)a Return an element of the preimage of ``g`` or of each element of ``g`` if ``g`` is a list. Explanation =========== If the codomain is an FpGroup, the inverse for equal elements might not always be the same unless the FpGroup's rewriting system is confluent. However, making a system confluent can be time-consuming. If it's important, try `self.codomain.make_confluent()` first. r Permutation)FreeGroupElementNr)sympy.combinatoricsr/sympy.combinatorics.free_groupsr0rrrreducerr,rrr"rgenerator_productrangelenrrinvert) rr(r/r0rr)r'ir+es rr7zGroupHomomorphism.invert?s4 4D a+'78 9$--1MM((+~~%!%JJLE $$A$--)9:..q1$B$73t9% 4G==&$..++A$..B/33A 4H 4 ,-.qDKKN. .!.sE"c\|j|j|_|jS)z0 Compute the kernel of `self`. )r_compute_kernelrs rkernelzGroupHomomorphism.kernelms( << //1DL||rcR|j}|j}|tjur t dg}t |t rt |j}nt||d}|jj}|j|z|k7r|j}||j||dzz}||vr;|j|t |t r t |}nt||d}|j|z|k7r|S)Nz9Kernel computation is not implemented for infinite groupsT)normalr) rorderr InfinityNotImplementedErrorrrr"rrrandomr7append)rGG_orderr'Kr8rr%s rr;z!GroupHomomorphism._compute_kernelvs KK'') ajj %KM M a) * ,A1d40A JJL   ggikW$ A$++d1g&**Az Aa!12(.A"1d48AggikW$rcL|jtt|jj }t |j tr,|j j||_|jSt|j ||_|jS)z/ Compute the image of `self`. ) rrsetrvaluesrrrsubgroupr)rrKs rrzGroupHomomorphism.imagesy ;; #dkk00234F$--)9:"mm44V< {{)? {{rc||jvr@t|ttfr|Dcgc]}|j |c}St d|j r|jjS|j}|jj}t|jtrK|jj|d}|D]'}||jvr |||z}||dzdz|z})|Sd}|jD]1\}} | dkr ||dz}n||}|||| zz}|t| z }3|Scc}w)z* Apply `self` to `elem`. z2The supplied element does not belong to the domainT)originalrr)rrrtuple_apply ValueErrorrrr"rrr4 array_formabs) relemr9rvaluer'r(r8_ps rrPzGroupHomomorphism._applysH t{{ "$u .0451 A55QR R   ==)) )[[FMM**E$++'78{{44TD4I8ADKK' &q % &q"u r 1% 7 8  OO DAq1u GRK G!&)Q,.EQKA   /6sD<c$|j|Sr)rP)rrTs r__call__zGroupHomomorphism.__call__s{{4  rcD|jjdk(S)z9 Check if the homomorphism is injective )r=r@r<s r is_injectivezGroupHomomorphism.is_injectives {{}""$))rc|jj}|jj}|tjur|tjury||k(S)z: Check if the homomorphism is surjective N)rr@rr rA)rimoths r is_surjectivezGroupHomomorphism.is_surjectivesN ZZ\   !mm!!#  qzz 19 rcF|jxr|jS)z5 Check if `self` is an isomorphism. )r\r`r<s ris_isomorphismz GroupHomomorphism.is_isomorphisms!   ";t'9'9';;rcD|jjdk(S)zs Check is `self` is a trivial homomorphism, i.e. all elements are mapped to the identity. r[)rr@r<s r is_trivialzGroupHomomorphism.is_trivials zz|!!#q((rc |jj|js td|jDcic]}||||}}t |j|j |Scc}w)z Return the composition of `self` and `other`, i.e. the homomorphism phi such that for all g in the domain of `other`, phi(g) = self(other(g)) z?The image of `other` must be a subgroup of the domain of `self`)r is_subgrouprrQrr r)rotherr(rs rcomposezGroupHomomorphism.composesn{{}((5+, ,-2\\:!T%(^#:: t}}fEE;sA<ct|tr|j|js t d|}|j Dcic] }||| }}t ||j|Scc}w)zh Return the restriction of the homomorphism to the subgroup `H` of the domain. z'Given H is not a subgroup of the domain)rrrfrrQr!r r)rHrr(rs r restrict_tozGroupHomomorphism.restrict_tosf !-.ammDKK6PFG G&'ll3!T!W*33 ??4sA0c|j|js tdg}t|jj}|j D]y}|j |}||vr|j|t|}|jj D])}||z|vs |j||zt|}+{|S)z Return the subgroup of the domain that is the inverse image of the subgroup ``H`` of the homomorphism image z&Given H is not a subgroup of the image) rfrrQrr"r!r7rDr=)rrjr'Phh_ir%s rinvert_subgroupz!GroupHomomorphism.invert_subgroups }}TZZ\*EF F TZZ\22 3 /A++a.C!| C $T*[[]-- /S5>KK#&(.A /  /rN)__name__ __module__ __qualname____doc__rr,r7r=r;rrPrYr\r`rbrdrhrkrprrr r sW!F,/\. @!* <) F @rr ct|tttfs t dttttfs t d|j t fd|Ds tdt fd|Ds td|r"t|t|k7r tdt|}t|}|jjgtt|z z|jDcgc] }||vs| c}tt||}|rt||s tdt||Scc}w) a Create (if possible) a group homomorphism from the group ``domain`` to the group ``codomain`` defined by the images of the domain's generators ``gens``. ``gens`` and ``images`` can be either lists or tuples of equal sizes. If ``gens`` is a proper subset of the group's generators, the unspecified generators will be mapped to the identity. If the images are not specified, a trivial homomorphism will be created. If the given images of the generators do not define a homomorphism, an exception is raised. If ``check`` is ``False``, do not check whether the given images actually define a homomorphism. zThe domain must be a groupzThe codomain must be a groupc3&K|]}|v ywrru).0r(r!s r zhomomorphism..#s-1qJ-zCThe supplied generators must be a subset of the domain's generatorsc3&K|]}|v ywrru)rxr(rs rryzhomomorphism..%s-qH}-rzz+The images must be elements of the codomainz>The number of images must be equal to the number of generatorsz-The given images do not define a homomorphism)rrrr TypeErrorr!allrQr6rextendr"dictzip_check_homomorphismr )rrr'rcheckr(r!s ` @r homomorphismr s4 f/)D E455 h!17I F G677""J -- -^__ -f- -FGG #f+T*YZZ :D &\F MM8$$%s:s6{'BCDKKJ8q!4-89 #d6" #F (6BHII VXv 66 9s  E' E'c t|dr|n|j}|j}|j}|Dcgc]}|jd}}t t ||j |j  fd}|D]y} t|trQ|j||  } | I|j} |j||  } | | std|| j} | ryyycc}w)a] Check that a given mapping of generators to images defines a homomorphism. Parameters ========== domain : PermutationGroup, FpGroup, FreeGroup codomain : PermutationGroup, FpGroup, FreeGroup images : dict The set of keys must be equal to domain.generators. The values must be elements of the codomain. relatorsrcT}|jD]\}}|}|||zz}|Sr)rR)rHr)symbolpowerr(r"rsymbols_to_domain_generatorss rrz#_check_homomorphism.._imageJsC \\ "MFE,V4A E! !A "rzCan't determine if the images define a homomorphism. Try increasing the maximum number of rewriting rules (group._rewriting_system.set_max(new_value); the current value is stored in group._rewriting_system.maxeqns)FT)hasattr presentationrr!ext_reprrr"rrequalsmake_confluent RuntimeErrorr)rrrpresrelsr'r(symbolsrrHr+successr"rs ` @@rrr6sVZ06f6I6I6KD ==D ??D%)*qyy|*G*#'GV5F5F(G#H   H h (q 84Ay#113OOF1Ix89W&(+,,q %%A'( ?+sDcddlm}ddlm}|t |}|j }t |}|jDcic].}||||Dcgc]}|j||z c}z0}}}|j|t|||} t |jt |kDr|jt || _ | St|j g| _ | Scc}wcc}}w)z Return the homomorphism induced by the action of the permutation group ``group`` on the set ``omega`` that is closed under the action. rr.SymmetricGroup)base)r1r/ sympy.combinatorics.named_groupsrr6r"rr!index_schreier_simsr basic_stabilizersrr) groupomegar/rrr"r(orrjs rorbit_homomorphismrgs 0?c%j)H  H KERWRbRb cQa+&GAu{{1Q3'7&GHHH cF c e$%62A 5 " "#c%j0++CJ7  H%enn%56 H'H cs C;C6, C;6C;c ddlm}ddlm}t |}d}g}dg|z}t |D]&}|||k(s |j ||||<|dz }(t |D] }|||||<||} t |} |jD cic]"} | || Dcgc] }|||| z c}$} } }t|| | } | Scc}wcc}} w)ab Return the homomorphism induced by the action of the permutation group ``group`` on the block system ``blocks``. The latter should be of the same form as returned by the ``minimal_block`` method for permutation groups, namely a list of length ``group.degree`` where the i-th entry is a representative of the block i belongs to. rr.rNr[) r1r/rrr6r5rDr!r )rblocksr/rnmrWbr8rr"r(rrjs rblock_homomorphismr{s0? F A A A qA 1X !9> HHQKAaD FA  1X|!a HQxHEJEUEU Va:Aa!Qi:;; VF V%62A H; Vs CC 1 C CcTt|ttfs tdt|ttfs tdt|trt|trt |}t |}|j |j k(r\|j j|j jk(r'|sydt|||j |j fS|}|j}|j}|tjur tdt|tr0|tjur td|j\}}||k7s|j|jk7r|syy|s|}t|t!|dk(ryt#|j }t%j&|t)|D]} t#| } | j+|j,gt)|j t)| z zt/t1|| } t3||| sot|trj5| } t|||j | d} | j7s|syd| fcS|syy)aE Compute an isomorphism between 2 given groups. Parameters ========== G : A finite ``FpGroup`` or a ``PermutationGroup``. First group. H : A finite ``FpGroup`` or a ``PermutationGroup`` Second group. isomorphism : bool This is used to avoid the computation of homomorphism when the user only wants to check if there exists an isomorphism between the groups. Returns ======= If isomorphism = False -- Returns a boolean. If isomorphism = True -- Returns a boolean and an isomorphism between `G` and `H`. Examples ======== >>> from sympy.combinatorics import free_group, Permutation >>> from sympy.combinatorics.perm_groups import PermutationGroup >>> from sympy.combinatorics.fp_groups import FpGroup >>> from sympy.combinatorics.homomorphisms import group_isomorphism >>> from sympy.combinatorics.named_groups import DihedralGroup, AlternatingGroup >>> D = DihedralGroup(8) >>> p = Permutation(0, 1, 2, 3, 4, 5, 6, 7) >>> P = PermutationGroup(p) >>> group_isomorphism(D, P) (False, None) >>> F, a, b = free_group("a, b") >>> G = FpGroup(F, [a**3, b**3, (a*b)**2]) >>> H = AlternatingGroup(4) >>> (check, T) = group_isomorphism(G, H) >>> check True >>> T(b*a*b**-1*a**-1*b**-1) (0 2 3) Notes ===== Uses the approach suggested by Robert Tarjan to compute the isomorphism between two groups. First, the generators of ``G`` are mapped to the elements of ``H`` and we check if the mapping induces an isomorphism. z2The group must be a PermutationGroup or an FpGroupTzrsMTT5<#9"BBH'7R/b (" Hrh6r