K i]dZddlmZddlmZddlmZddlmZddl m Z ddl m Z ddl mZdd lmZd d lmZmZd d lmZd d lmZmZd dlmZmZdZGddeZdZedZddZ dZ!dZ"dZ#dZ$eddZ%y)zPrime ideals in number fields. )Poly)FF)QQ)ZZ) DomainMatrix)CoercionFailed)IntegerPowerable)public) round_twonilradical_mod_p)StructureError)ModuleEndomorphism find_min_poly) coeff_searchsupplement_a_subspacecd}d}|jsd}n%|jsd}n|jsd}|t||zy)a Several functions in this module accept an argument which is to be a :py:class:`~.Submodule` representing the maximal order in a number field, such as returned by the :py:func:`~sympy.polys.numberfields.basis.round_two` algorithm. We do not attempt to check that the given ``Submodule`` actually represents a maximal order, but we do check a basic set of formal conditions that the ``Submodule`` must satisfy, at a minimum. The purpose is to catch an obviously ill-formed argument. z4The submodule representing the maximal order should Nz'be a direct submodule of a power basis.zhave 1 as its first generator.z>> from sympy import cyclotomic_poly, QQ >>> from sympy.abc import x, zeta >>> T = cyclotomic_poly(7, x) >>> K = QQ.algebraic_field((T, zeta)) >>> P = K.primes_above(11) >>> print(P[0].repr()) [ (11, x**3 + 5*x**2 + 4*x - 1) e=1, f=3 ] >>> print(P[0].repr(field_gen=zeta)) [ (11, zeta**3 + 5*zeta**2 + 4*zeta - 1) e=1, f=3 ] >>> print(P[0].repr(field_gen=zeta, just_gens=True)) (11, zeta**3 + 5*zeta**2 + 4*zeta - 1) Parameters ========== field_gen : :py:class:`~.Symbol`, ``None``, optional (default=None) The symbol to use for the generator of the field. This will appear in our representation of ``self.alpha``. If ``None``, we use the variable of the defining polynomial of ``self.ZK``. just_gens : bool, optional (default=False) If ``True``, just print the "(p, alpha)" part, showing "just the generators" of the prime ideal. Otherwise, print a string of the form "[ (p, alpha) e=..., f=... ]", giving the ramification index and inertia degree, along with the generators. )xr r*z)/r,r+z[ z e=z, f=z ]) r parentTgenr!r"r&r#str numeratorr.denom) r' field_gen just_gensr!r"r&r# alpha_repgenss rreprzPrimeIdeal.reprUsB5!1!1!5!5 TVVTVV;5!Q)4<<>? ;;?I;b 6I1#R {!$ KD6QCtA3b))rc"|jSN)r?r/s r__repr__zPrimeIdeal.__repr__syy{rc|j|jz|j|jzz}d|_d|_|S)a Represent this prime ideal as a :py:class:`~.Submodule`. Explanation =========== The :py:class:`~.PrimeIdeal` class serves to bundle information about a prime ideal, such as its inertia degree, ramification index, and two-generator representation, as well as to offer helpful methods like :py:meth:`~.PrimeIdeal.valuation` and :py:meth:`~.PrimeIdeal.test_factor`. However, in order to be added and multiplied by other ideals or rational numbers, it must first be converted into a :py:class:`~.Submodule`, which is a class that supports these operations. In many cases, the user need not perform this conversion deliberately, since it is automatically performed by the arithmetic operator methods :py:meth:`~.PrimeIdeal.__add__` and :py:meth:`~.PrimeIdeal.__mul__`. Raising a :py:class:`~.PrimeIdeal` to a non-negative integer power is also supported. Examples ======== >>> from sympy import Poly, cyclotomic_poly, prime_decomp >>> T = Poly(cyclotomic_poly(7)) >>> P0 = prime_decomp(7, T)[0] >>> print(P0**6 == 7*P0.ZK) True Note that, on both sides of the equation above, we had a :py:class:`~.Submodule`. In the next equation we recall that adding ideals yields their GCD. This time, we need a deliberate conversion to :py:class:`~.Submodule` on the right: >>> print(P0 + 7*P0.ZK == P0.as_submodule()) True Returns ======= :py:class:`~.Submodule` Will be equal to ``self.p * self.ZK + self.alpha * self.ZK``. See Also ======== __add__ __mul__ FT)r!r r"_starts_with_unity_is_sq_maxrank_HNF)r'Ms r as_submodulezPrimeIdeal.as_submodules>n FFTWW tzzDGG3 3$#rcpt|tr!|j|jk(StSrA) isinstancerrGNotImplementedr'others r__eq__zPrimeIdeal.__eq__s/ eZ ($$&%*<*<*>> >rc(|j|zS)z Convert to a :py:class:`~.Submodule` and add to another :py:class:`~.Submodule`. See Also ======== as_submodule rGrKs r__add__zPrimeIdeal.__add__  "U**rc(|j|zS)z Convert to a :py:class:`~.Submodule` and multiply by another :py:class:`~.Submodule` or a rational number. See Also ======== as_submodule rOrKs r__mul__zPrimeIdeal.__mul__rQrc|jSrA)r r/s r _zeroth_powerzPrimeIdeal._zeroth_powers wwrc|SrAr/s r _first_powerzPrimeIdeal._first_powers rc|j1t|j|jg|j|_|jS)aO Compute a test factor for this prime ideal. Explanation =========== Write $\mathfrak{p}$ for this prime ideal, $p$ for the rational prime it divides. Then, for computing $\mathfrak{p}$-adic valuations it is useful to have a number $\beta \in \mathbb{Z}_K$ such that $p/\mathfrak{p} = p \mathbb{Z}_K + \beta \mathbb{Z}_K$. Essentially, this is the same as the number $\Psi$ (or the "reagent") from Kummer's 1847 paper (*Ueber die Zerlegung...*, Crelle vol. 35) in which ideal divisors were invented. )r$_compute_test_factorr!r"r r/s r test_factorzPrimeIdeal.test_factors;    $ 4TVVdjj\477 SD    rct||S)z Compute the $\mathfrak{p}$-adic valuation of integral ideal I at this prime ideal. Parameters ========== I : :py:class:`~.Submodule` See Also ======== prime_valuation )prime_valuation)r'Is rr%zPrimeIdeal.valuations q$''rc@|jj|S)a Reduce a :py:class:`~.PowerBasisElement` to a "small representative" modulo this prime ideal. Parameters ========== elt : :py:class:`~.PowerBasisElement` The element to be reduced. Returns ======= :py:class:`~.PowerBasisElement` The reduced element. See Also ======== reduce_ANP reduce_alg_num .Submodule.reduce_element )rGreduce_element)r'elts rr`zPrimeIdeal.reduce_elements2  "11#66rc|jjj|}|j|}|j S)a Reduce an :py:class:`~.ANP` to a "small representative" modulo this prime ideal. Parameters ========== elt : :py:class:`~.ANP` The element to be reduced. Returns ======= :py:class:`~.ANP` The reduced element. See Also ======== reduce_element reduce_alg_num .Submodule.reduce_element )r r5element_from_ANPr`to_ANPr'arareds r reduce_ANPzPrimeIdeal.reduce_ANP*s82ggnn--a0!!#&zz|rc|jjj|}|j|}|j t t |jjS)a Reduce an :py:class:`~.AlgebraicNumber` to a "small representative" modulo this prime ideal. Parameters ========== elt : :py:class:`~.AlgebraicNumber` The element to be reduced. Returns ======= :py:class:`~.AlgebraicNumber` The reduced element. See Also ======== reduce_element reduce_ANP .Submodule.reduce_element ) r r5element_from_alg_numr` field_elementlistreversedQQ_colflatres rreduce_alg_numzPrimeIdeal.reduce_alg_numGsP2ggnn11!4!!#&tHSZZ__->$?@AArrA)NF)__name__ __module__ __qualname____doc__r(r0propertyr-r?rBrGrMrP__radd__rS__rmul__rUrXr[r%r`rhrprWrrrr)sx@45 ##)*V;z +H +H!(($76:Brrct||j}|Dcgc]#}|j|j|%}}t j d|j ft|j|}|jdddfj}|j|j|jtz|j}|Scc}w)a Compute the test factor for a :py:class:`~.PrimeIdeal` $\mathfrak{p}$. Parameters ========== p : int The rational prime $\mathfrak{p}$ divides gens : list of :py:class:`PowerBasisElement` A complete set of generators for $\mathfrak{p}$ over *ZK*, EXCEPT that an element equivalent to rational *p* can and should be omitted (since it has no effect except to waste time). ZK : :py:class:`~.Submodule` The maximal order where the prime ideal $\mathfrak{p}$ lives. Returns ======= :py:class:`~.PowerBasisElement` References ========== .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.* (See Proposition 4.8.15.) modulusrNr:)rendomorphism_ringinner_endomorphismmatrixrzerosr2rvstack nullspace transposer5 convert_torr:) r!r>r EgmatricesBr4betas rrZrZes</r2 ACGHa$$Q'..q.9HHH3 Artt9be,33X>A ad%%'A 99RYYb!119 BD KIs(C&cd|j|j}}|j|j|j}}}|j t j|jz|z|jz }|j t}|j}||zdk7ry|j} ||z|jz} | |zdk(} d} ||z}t|D]Z} |j|dd| f|}|| z}|j|j}t|D] }||||| f<\||dz |dz fj|zdk7r | S||z }| r |j t}n|j t}| dz } #t $rY| SwxYw)a Compute the *P*-adic valuation for an integral ideal *I*. Examples ======== >>> from sympy import QQ >>> from sympy.polys.numberfields import prime_valuation >>> K = QQ.cyclotomic_field(5) >>> P = K.primes_above(5) >>> ZK = K.maximal_order() >>> print(prime_valuation(25*ZK, P[0])) 8 Parameters ========== I : :py:class:`~.Submodule` An integral ideal whose valuation is desired. P : :py:class:`~.PrimeIdeal` The prime at which to compute the valuation. Returns ======= int See Also ======== .PrimeIdeal.valuation References ========== .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.* (See Algorithm 4.8.17.) rNr{r )r!r r2r~r:rrinvrdetr[ranger5 representroelementr)r^Pr!r r2WdADrr#need_complete_testvjcis rr]r]sT CCrAddBIIrxx!qA R)A-7A RA A1uz ==?D Q!%%'Aa%1* A  Eq A !AqD' +A IA Q$$&A1X A$!Q$    QUAE\? " "Q &! +  H E  LL$  R A Q7 ,"  H  s1F"" F/.F/Nc t||j}|j}tfd|Dr|j S|:||z}n2t |j |jj}|j}|ddDcgc]}|z } }| |z } tt| d} | D]A} tdt| | D} | j||z} | zdk7s<| zcSycc}w)a Given a set of *ZK*-generators of a prime ideal, compute a set of just two *ZK*-generators for the same ideal, one of which is *p* itself. Parameters ========== gens : list of :py:class:`PowerBasisElement` Generators for the prime ideal over *ZK*, the ring of integers of the field $K$. ZK : :py:class:`~.Submodule` The maximal order in $K$. p : int The rational prime divided by the prime ideal. f : int, optional The inertia degree of the prime ideal, if known. Np : int, optional The norm $p^f$ of the prime ideal, if known. NOTE: There is no reason to supply both *f* and *Np*. Either one will save us from having to compute the norm *Np* ourselves. If both are known, *Np* is preferred since it saves one exponentiation. Returns ======= :py:class:`~.PowerBasisElement` representing a single algebraic integer alpha such that the prime ideal is equal to ``p*ZK + alpha*ZK``. References ========== .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.* (See Algorithm 4.7.10.) c3FK|]}|zjdyw)rN)equiv).0rr!s r z_two_elt_rep..s *AE==  *s!Nr c3,K|] \}}||zywrArW)rcibetais rrz_two_elt_rep..'s;UBuH;sr)rr5r6allzeroabssubmodule_from_gensr~rbasis_element_pullbacksrlensumzipnorm)r>r r!r#Nppbr6omegaomrsearchrr"r2s ` r _two_elt_reprs P/r2 B A *T **wwy z =ABR++D188<<>?B  & & (E 9 %RAbD %D %DLD #d)Q 'F ;c!Tl;; JJqMR  q5A:19  &s D c|jj}t||}|j\}}t |dk(r=|dddk(r2t |||jj |jdgS|Dcgc]J\}}t |||jjt|t|j|Lc}}Scc}}w)a? Compute the decomposition of rational prime *p* in the ring of integers *ZK* (given as a :py:class:`~.Submodule`), in the "easy case", i.e. the case where *p* does not divide the index of $\theta$ in *ZK*, where $\theta$ is the generator of the ``PowerBasis`` of which *ZK* is a ``Submodule``. ryr rdomain) r5r6r factor_listrrrr2element_from_polyrdegree)r!r r6T_barlcfltr&s r_prime_decomp_easy_caser1s A A E    FB 2w!|1aA 2q")).."2BDD!<== 1 r1yy224"3EFxxz1 &  sACc,|j}|j\}}|dk(r|j|t}n,|j |j|tdddf}|jd|kr6t |j tj t}|j|}|j|j|}t|fd}|j} | jsJ| |fS)a+ Parameters ========== I : :py:class:`~.Module` An ideal of ``ZK/pZK``. p : int The rational prime being factored. ZK : :py:class:`~.Submodule` The maximal order. Returns ======= Pair ``(N, G)``, where: ``N`` is a :py:class:`~.Module` representing the kernel of the map ``a |--> a**p - a`` on ``(O/pO)/I``, guaranteed to be a module with unity. ``G`` is a :py:class:`~.Module` representing a basis for the separable algebra ``A = O/I`` (see Cohen). rNr c|z|z SrArW)r4r!s rz._prime_decomp_compute_kernel..ss!Q$(rry)r~shapeeyerhstackrrrsubmodule_from_matrixcompute_mult_tabdiscard_beforerkernelr) r^r!r rr2rrGphiNs ` r_prime_decomp_compute_kernelrDs2 A 77DAq  Av EE!RL HHQUU1b\!Q$' (wwqzA~ !!,,r!u"5 6 A A" E   #A  A Q 2 3C 1 A    a4KrcB|jj\}}||z }|j|jz}t|jdDcgc]&}|j|dd|f|j(}}t ||||} t ||| |Scc}w)a We have reached the case where we have a maximal (hence prime) ideal *I*, which we know because the quotient ``O/I`` is a field. Parameters ========== I : :py:class:`~.Module` An ideal of ``O/pO``. p : int The rational prime being factored. ZK : :py:class:`~.Submodule` The maximal order. Returns ======= :py:class:`~.PrimeIdeal` instance representing this prime r Nr{)r#)r~rrr5r:rr) r^r!r mr2r#rrr>r"s r_prime_decomp_maximal_idealrys* 88>>DAq AA AHHA8=aggaj8I J1BIIa1gRXXI . JD J r1 *E b!UA && Ks+Bc |j|k(r|j|ur|j|usJ|dj}|j|usJgt|t |}|j \}}|dd} |j | } | j| \} } } | dk(sJttt| | ztjjtfdtt!D}d|z }||g}g}|D]}|j}|j|usJ|j"j%t |j&|j)Dcgc] }||zj+t |"c}}|j-j%t}|j/|}|j1||Scc}w)z Perform the step in the prime decomposition algorithm where we have determined the quotient ``ZK/I`` is _not_ a field, and we want to perform a non-trivial factorization of *I* by locating an idempotent element of ``ZK/I``. r )powersrrc34K|]}||zywrArW)rrr alpha_powerss rrz,_prime_decomp_split_ideal..s;qtLO#;s)r5 to_parentmodulerrrquogcdexrlrmrrrepto_listrrrr~rrbasis_elementscolumn columnspacerappend)r^r!rrr r"rrrm1m2UVreps1eps2idempsfactorsepsr&rrrHrrs @@r_prime_decomp_split_idealrs 88r>ahh"nQ> > aDNN E <<1  LeRU<8A]]_FB AqB rBhhrlGAq! 6M6 Xd1r6"-1199; <=A ;U3q6]; ;D t8DD\FG MMOxx2~~ -AHH  1 & - -464E4E4G0 .0QVOO2a5O )0   MMO & &r *  $ $Q 'q N 0 s %G> c,| | td| t|||jj}i}||t ||\}}|j }||z}||zdk7r t ||S|xs|j|xs t||}|g}g} |rv|j} t| ||\} } | jdk(rt| ||} | j| n%t| || | |\}}|j||g|rv| S)a Compute the decomposition of rational prime *p* in a number field. Explanation =========== Ordinarily this should be accessed through the :py:meth:`~.AlgebraicField.primes_above` method of an :py:class:`~.AlgebraicField`. Examples ======== >>> from sympy import Poly, QQ >>> from sympy.abc import x, theta >>> T = Poly(x ** 3 + x ** 2 - 2 * x + 8) >>> K = QQ.algebraic_field((T, theta)) >>> print(K.primes_above(2)) [[ (2, x**2 + 1) e=1, f=1 ], [ (2, (x**2 + 3*x + 2)/2) e=1, f=1 ], [ (2, (3*x**2 + 3*x)/2) e=1, f=1 ]] Parameters ========== p : int The rational prime whose decomposition is desired. T : :py:class:`~.Poly`, optional Monic irreducible polynomial defining the number field $K$ in which to factor. NOTE: at least one of *T* or *ZK* must be provided. ZK : :py:class:`~.Submodule`, optional The maximal order for $K$, if already known. NOTE: at least one of *T* or *ZK* must be provided. dK : int, optional The discriminant of the field $K$, if already known. radical : :py:class:`~.Submodule`, optional The nilradical mod *p* in the integers of $K$, if already known. Returns ======= List of :py:class:`~.PrimeIdeal` instances. References ========== .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.* (See Algorithm 6.2.9.) z)At least one of T or ZK must be provided.)radicalsrr ) ValueErrorrr5r6r discriminantrgetr poprr2rrrextend)r!r6r dKradicalrdT f_squaredstackprimesr^rrrI1I2s r prime_decomprs'n yRZDEE ~226y IIKKH zRZ1x0B  BbI1}&q"--CaC,FB LL"b "  Mr)NN)NNNN)&rtsympy.polys.polytoolsrsympy.polys.domains.finitefieldr!sympy.polys.domains.rationalfieldrsympy.polys.domains.integerringr!sympy.polys.matrices.domainmatrixrsympy.polys.polyerrorsrsympy.polys.polyutilsr sympy.utilities.decoratorr basisr r exceptionsrmodulesrr utilitiesrrrrrZr]rrrrrrrWrrrs%&.0.:12,.&6:,0yB!yBx +\U U pBJ&2j':'TOOr