K iM`dZddlmZmZmZmZmZmZmZm Z m Z m Z ddl m Z mZmZmZmZmZmZmZmZmZmZmZddlmZmZmZmZmZmZm Z m!Z!m"Z"ddl#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)ddl*m+Z+m,Z,ddl-m.Z.m/Z/dZ0d Z1d Z2d Z3d Z4d Z5dZ6dZ7dZ8dZ9dZ:dZ;ddZddZ?ddZ@ddZAdZBdZCy)z8Square-free decomposition algorithms and related tools. ) dup_negdmp_negdup_subdmp_subdup_muldmp_muldup_quodmp_quodup_mul_grounddmp_mul_ground) dup_stripdup_LC dmp_ground_LC dmp_zero_p dmp_ground dup_degree dmp_degree dmp_degree_indmp_degree_list dmp_raise dmp_inject dup_convert) dup_diffdmp_diff dmp_diff_in dup_shift dmp_shift dup_monicdmp_ground_monic dup_primitivedmp_ground_primitive) dup_inner_gcd dmp_inner_gcddup_gcddmp_gcd dmp_resultant dmp_primitive) gf_sqf_list gf_sqf_part)MultivariatePolynomialError DomainErrorcHtd|D}|t|k(sJy)z=Sanity check the degrees of a computed factorization in K[x].c3>K|]\}}|t|zyw)N)r).0facks ]/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/polys/sqfreetools.py z%_dup_check_degrees..$s 9hsAa*S/! 9sN)sumr)fresultdegs r1_dup_check_degreesr7"s$ 9& 9 9C *Q-  cdg|dzz}|D]5\}}t||}t||Dcgc] \}}|||zz}}}7t|t||k(sJycc}}w)z=Sanity check the degrees of a computed factorization in K[X].rN)rziptuple) r4ur5degsr/r0degs_facd1d2s r1_dmp_check_degreesrB(sv 3!a%=D?Q"3**-dH*=>BQV >>? ;/!Q/ // /?sAc L|sytt|t|d|| S)a Return ``True`` if ``f`` is a square-free polynomial in ``K[x]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> R.dup_sqf_p(x**2 - 2*x + 1) False >>> R.dup_sqf_p(x**2 - 1) True Tr:)rr$r)r4Ks r1 dup_sqf_prE1s* ga!Q):A>???r8ct||ryt|dzD]>}t|d|||}t||rt||||}t |||dk7s>yy)a Return ``True`` if ``f`` is a square-free polynomial in ``K[X]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) >>> R.dmp_sqf_p(x**2 + 2*x*y + y**2) False >>> R.dmp_sqf_p(x**2 + y**2) True Tr:rF)rrangerr%r)r4r=rDifpgcds r1 dmp_sqf_prKGsp !Q 1Q3Z  Aq!Q ' b!  aQ" a #q (  r8c^|js tddt|jj dd|j }} t |d|d\}}t||d|j }t||j rnt||j ||dz}}_|||fS)ag Find a shift of `f` in `K[x]` that has square-free norm. The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`). Returns `(s,g,r)`, such that `g(x)=f(x-sa)`, `r(x)=\text{Norm}(g(x))` and `r` is a square-free polynomial over `k`. Examples ======== We first create the algebraic number field `K=k(a)=\mathbb{Q}(\sqrt{3})` and rings `K[x]` and `k[x]`: >>> from sympy.polys import ring, QQ >>> from sympy import sqrt >>> K = QQ.algebraic_field(sqrt(3)) >>> R, x = ring("x", K) >>> _, X = ring("x", QQ) We can now find a square free norm for a shift of `f`: >>> f = x**2 - 1 >>> s, g, r = R.dup_sqf_norm(f) The choice of shift `s` is arbitrary and the particular values returned for `g` and `r` are determined by `s`. >>> s == 1 True >>> g == x**2 - 2*sqrt(3)*x + 2 True >>> r == X**4 - 8*X**2 + 4 True The invariants are: >>> g == f.shift(-s*K.unit) True >>> g.norm() == r True >>> r.is_squarefree True Explanation =========== This is part of Trager's algorithm for factorizing polynomials over algebraic number fields. In particular this function is algorithm ``sqfr_norm`` from [Trager76]_. See Also ======== dmp_sqf_norm: Analogous function for multivariate polynomials over ``k(a)``. dmp_norm: Computes the norm of `f` directly without any shift. dup_ext_factor: Function implementing Trager's algorithm that uses this. sympy.polys.polytools.sqf_norm: High-level interface for using this function. ground domain must be algebraicrr:Tfront) is_Algebraicr+rmodto_listdomrr&rErunit)r4rDsgh_rs r1 dup_sqf_normrZisB >>;<< i Aquu5qA !Q.1 !Q155 ) Q  Q+QUqA  a7Nr8c #K|dz}dg|z}||f|j}t||}tt|t |dzDcgc] \}}|dkDs |} }}| D]>}|j } d| |<| D cgc]} | | z } } t || ||} | | f@d} |dz }|g|z}| |zg|z}t ||||}||f*cc}}wcc} ww)z9Generate a sequence of candidate shifts for dmp_sqf_norm.r:r)rTrsortedr;rGcopyr)r4r=rDns0addirH var_indicess1s1ia1f1jsjajfjs r1_dmp_sqf_norm_shiftsrls AA qB a%K A 1A"(Qac );"<GQQ1GKG WWY1 " #qbf # # q"a #"f  A  QS1WbdVaZ q"a #"f H $s%AC  CC"!C  CAC c|st||\}}}|g||fS|js tdt|jj |dzd|j }t|||D]K\}}t|||d\}}t|||dz|j }t|||j sKn|fS)a Find a shift of ``f`` in ``K[X]`` that has square-free norm. The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`). Returns `(s,g,r)`, such that `g(x_1,x_2,\cdots)=f(x_1-s_1 a, x_2 - s_2 a, \cdots)`, `r(x)=\text{Norm}(g(x))` and `r` is a square-free polynomial over `k`. Examples ======== We first create the algebraic number field `K=k(a)=\mathbb{Q}(i)` and rings `K[x,y]` and `k[x,y]`: >>> from sympy.polys import ring, QQ >>> from sympy import I >>> K = QQ.algebraic_field(I) >>> R, x, y = ring("x,y", K) >>> _, X, Y = ring("x,y", QQ) We can now find a square free norm for a shift of `f`: >>> f = x*y + y**2 >>> s, g, r = R.dmp_sqf_norm(f) The choice of shifts ``s`` is arbitrary and the particular values returned for ``g`` and ``r`` are determined by ``s``. >>> s [0, 1] >>> g == x*y - I*x + y**2 - 2*I*y - 1 True >>> r == X**2*Y**2 + X**2 + 2*X*Y**3 + 2*X*Y + Y**4 + 2*Y**2 + 1 True The required invariants are: >>> g == f.shift_list([-si*K.unit for si in s]) True >>> g.norm() == r True >>> r.is_squarefree True Explanation =========== This is part of Trager's algorithm for factorizing polynomials over algebraic number fields. In particular this function is a multivariate generalization of algorithm ``sqfr_norm`` from [Trager76]_. See Also ======== dup_sqf_norm: Analogous function for univariate polynomials over ``k(a)``. dmp_norm: Computes the norm of `f` directly without any shift. dmp_ext_factor: Function implementing Trager's algorithm that uses this. sympy.polys.polytools.sqf_norm: High-level interface for using this function. rMr:rTrN) rZrPr+rrQrRrSrlrr&rK)r4r=rDrUrVrYrWrXs r1 dmp_sqf_normrnsD q!$1asAqy >>;<<!%%--/1q5!QUU3A$Q1-1!Q.1 !QAquu - Q155 !   a7Nr8c|js tdt|jj |dzd|j }t |||d\}}t|||dz|j S)aE Norm of ``f`` in ``K[X]``, often not square-free. The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`). Examples ======== We first define the algebraic number field `K = k(a) = \mathbb{Q}(\sqrt{2})`: >>> from sympy import QQ, sqrt >>> from sympy.polys.sqfreetools import dmp_norm >>> k = QQ >>> K = k.algebraic_field(sqrt(2)) We can now compute the norm of a polynomial `p` in `K[x,y]`: >>> p = [[K(1)], [K(1),K.unit]] # x + y + sqrt(2) >>> N = [[k(1)], [k(2),k(0)], [k(1),k(0),k(-2)]] # x**2 + 2*x*y + y**2 - 2 >>> dmp_norm(p, 1, K) == N True In higher level functions that is: >>> from sympy import expand, roots, minpoly >>> from sympy.abc import x, y >>> from math import prod >>> a = sqrt(2) >>> e = (x + y + a) >>> e.as_poly([x, y], extension=a).norm() Poly(x**2 + 2*x*y + y**2 - 2, x, y, domain='QQ') This is equal to the product of the expressions `x + y + a_i` where the `a_i` are the conjugates of `a`: >>> pa = minpoly(a) >>> pa _x**2 - 2 >>> rs = roots(pa, multiple=True) >>> rs [sqrt(2), -sqrt(2)] >>> n = prod(e.subs(a, r) for r in rs) >>> n (x + y - sqrt(2))*(x + y + sqrt(2)) >>> expand(n) x**2 + 2*x*y + y**2 - 2 Explanation =========== Given an algebraic number field `K = k(a)` any element `b` of `K` can be represented as polynomial function `b=g(a)` where `g` is in `k[x]`. If the minimal polynomial of `a` over `k` is `p_a` then the roots `a_1`, `a_2`, `\cdots` of `p_a(x)` are the conjugates of `a`. The norm of `b` is the product `g(a1) \times g(a2) \times \cdots` and is an element of `k`. As in [Trager76]_ we extend this norm to multivariate polynomials over `K`. If `b(x)` is a polynomial in `k(a)[X]` then we can think of `b` as being alternately a function `g_X(a)` where `g_X` is an element of `k[X][y]` i.e. a polynomial function with coefficients that are elements of `k[X]`. Then the norm of `b` is the product `g_X(a1) \times g_X(a2) \times \cdots` and will be an element of `k[X]`. See Also ======== dmp_sqf_norm: Compute a shift of `f` so that the `\text{Norm}(f)` is square-free. sympy.polys.polytools.Poly.norm: Higher-level function that calls this. rMr:rTrN)rPr+rrQrRrSrr&)r4r=rDrVrWrXs r1dmp_normrp9sgP >>;<<!%%--/1q5!QUU3A aAT *DAq Aq1uaee ,,r8ct|||j}t||j|j}t||j|S)z3Compute square-free part of ``f`` in ``GF(p)[x]``. )rrSr)rQ)r4rDrVs r1dup_gf_sqf_partrrs=Aq!%% AAquuaee$A q!%% ##r8ctd)z3Compute square-free part of ``f`` in ``GF(p)[X]``. +multivariate polynomials over finite fieldsNotImplementedErrorr4r=rDs r1dmp_gf_sqf_partrx K LLr8c |jr t||S|s|S|jt||r t ||}t |t |d||}t|||}|jr t||St||dS)a Returns square-free part of a polynomial in ``K[x]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> R.dup_sqf_part(x**3 - 3*x - 2) x**2 - x - 2 See Also ======== sympy.polys.polytools.Poly.sqf_part r:) is_FiniteFieldrr is_negativerrr$rr is_Fieldrr )r4rDrJsqfs r1 dup_sqf_partrs$ q!$$ }}VAq\" AqM !XaA& *C !S! Czza  S!$Q''r8c |s t||S|jr t|||St||r|S|j t |||r t |||}|}t|dzD]}t|t|d|||||}t||||}|jr t|||St|||dS)z Returns square-free part of a polynomial in ``K[X]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) >>> R.dmp_sqf_part(x**3 + 2*x**2*y + x*y**2) x**2 + x*y r:)rr{rxrr|rrrGr%rr r}rr!)r4r=rDrJrHr~s r1 dmp_sqf_partrs Aq!!q!Q''!Q}}]1a+, Aq!  C 1Q3Z=c;q!Q15q!<= !S!Q CzzQ**#CA.q11r8c8|}t|||j}t||j|j|\}}t |D]$\}\}}t||j||f||<&t |||j ||j|fS)z>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> f = 2*x**5 + 16*x**4 + 50*x**3 + 76*x**2 + 56*x + 16 >>> R.dup_sqf_list(f) (2, [(x + 1, 2), (x + 2, 3)]) >>> R.dup_sqf_list(f, all=True) (2, [(1, 1), (x + 1, 2), (x + 2, 3)]) See Also ======== dmp_sqf_list: Corresponding function for multivariate polynomials. sympy.polys.polytools.sqf_list: High-level function for square-free factorization of expressions. sympy.polys.polytools.Poly.sqf_list: Analogous method on :class:`~.Poly`. References ========== [Yun76]_ rrr:)r{rr}rrr r|rrrr"rappendr7) r4rDrrrr5rHrWrVpqras r1 dup_sqf_listrs?D q!-- Fzzq!  aO A&q ==1 &1 AFE!}byAAFAqAAq!$GAq!  Q1  Aq!  MM1a& ! 1a(1a *Q-!# MM1a& ! Q vv& &=r8ct|||\}}|r)|dddk(rt|dd||}|dfg|ddzSt|g}|dfg|zS)a Return square-free decomposition of a polynomial in ``K[x]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> f = 2*x**5 + 16*x**4 + 50*x**3 + 76*x**2 + 56*x + 16 >>> R.dup_sqf_list_include(f) [(2, 1), (x + 1, 2), (x + 2, 3)] >>> R.dup_sqf_list_include(f, all=True) [(2, 1), (x + 1, 2), (x + 2, 3)] rrr:N)rr r )r4rDrrrrVs r1dup_sqf_list_includerAsr$"!QC0NE771:a=A% 71:a=% 3Ax'!"+%% ug Ax'!!r8ch|st|||S|jrt||||S|}|jrt |||}t |||}n>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) >>> f = x**5 + 2*x**4*y + x**3*y**2 >>> R.dmp_sqf_list(f) (1, [(x + y, 2), (x, 3)]) >>> R.dmp_sqf_list(f, all=True) (1, [(1, 1), (x + y, 2), (x, 3)]) Explanation =========== Uses Yun's algorithm for univariate polynomials from [Yun76]_ recursively. The multivariate polynomial is treated as a univariate polynomial in its leading variable. Then Yun's algorithm computes the square-free factorization of the primitive and the content is factored recursively. It would be better to use a dedicated algorithm for multivariate polynomials instead. See Also ======== dup_sqf_list: Corresponding function for univariate polynomials. sympy.polys.polytools.sqf_list: High-level function for square-free factorization of expressions. sympy.polys.polytools.Poly.sqf_list: Analogous method on :class:`~.Poly`. rrr:)rr{rr}rrr!r|rrr'rr#rr dmp_sqf_listrr\rB)r4r=rDrrrr6contentr5rWrVrrrHra coeff_contentresult_contentr/s r1rr]sL Aqc**q!QC00 FzzaA& Q1 %'1a0q ==q!Q/ 01a AFE Q C Qwbyq!Q'JGQ F ax Q1a 1a+1a Aq!$A1a#A!Qq #Aq!Q/GAq!jA&*q FA%1!A#qc$J!M> ]E!Qe ;q 315F1IF1I '-Vn 5vay!n 5F 5vq&) &= 6sF/c|st|||St||||\}}|r*|dddk(rt|dd|||}|dfg|ddzSt||}|dfg|zS)ah Return square-free decomposition of a polynomial in ``K[x]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) >>> f = x**5 + 2*x**4*y + x**3*y**2 >>> R.dmp_sqf_list_include(f) [(1, 1), (x + y, 2), (x, 3)] >>> R.dmp_sqf_list_include(f, all=True) [(1, 1), (x + y, 2), (x, 3)] rrr:N)rrr r)r4r=rDrrrrVs r1dmp_sqf_list_includers$ #Aqc22!!Qs3NE771:a=A% 71:a=%A 6Ax'!"+%% ua Ax'!!r8c l|s tdt||}t|sgSt|t ||j ||}t ||}t|D]1\}\}}t|t ||| ||}||dzf||<3t|||}t|s|S|dfg|zS)z Compute greatest factorial factorization of ``f`` in ``K[x]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x = ring("x", ZZ) >>> R.dup_gff_list(x**5 + 2*x**4 - x**3 - 2*x**2) [(x, 1), (x + 2, 4)] zDgreatest factorial factorization doesn't exist for a zero polynomialr:) ValueErrorrrr$rone dup_gff_listrrr )r4rDrVHrHrWr0s r1rrs _``!QA a= AyAEE1-q 1 A "1 IAv19Q1q115Aq1u:AaD  Aq! !}HF8a< r8c4|s t||St|)z Compute greatest factorial factorization of ``f`` in ``K[X]``. Examples ======== >>> from sympy.polys import ring, ZZ >>> R, x,y = ring("x,y", ZZ) )rr*rws r1 dmp_gff_listr s Aq!!)!,,r8N)F)D__doc__sympy.polys.densearithrrrrrrr r r r sympy.polys.densebasicr rrrrrrrrrrrsympy.polys.densetoolsrrrrrrrr r!sympy.polys.euclidtoolsr"r#r$r%r&r'sympy.polys.galoistoolsr(r)sympy.polys.polyerrorsr*r+r7rBrErKrZrlrnrprrrxrrrrrrrrrrr8r1rs>$$$ ))) ""  0@,DOd%PSlN-b$M !(H"2J , M JZ"8iX">" J-r8