K iAdZddlmZddlmZddlmZddlmZddl m Z m Z ddl m Z ddlmZdd lmZdd lmZmZdd lmZdd lmZmZmZdd lmZddlmZdZdZ dZ!edddZ"dZ#dZ$edddddZ%edddddZ&y)a@ Functions in ``polys.numberfields.subfield`` solve the "Subfield Problem" and allied problems, for algebraic number fields. Following Cohen (see [Cohen93]_ Section 4.5), we can define the main problem as follows: * **Subfield Problem:** Given two number fields $\mathbb{Q}(\alpha)$, $\mathbb{Q}(\beta)$ via the minimal polynomials for their generators $\alpha$ and $\beta$, decide whether one field is isomorphic to a subfield of the other. From a solution to this problem flow solutions to the following problems as well: * **Primitive Element Problem:** Given several algebraic numbers $\alpha_1, \ldots, \alpha_m$, compute a single algebraic number $\theta$ such that $\mathbb{Q}(\alpha_1, \ldots, \alpha_m) = \mathbb{Q}(\theta)$. * **Field Isomorphism Problem:** Decide whether two number fields $\mathbb{Q}(\alpha)$, $\mathbb{Q}(\beta)$ are isomorphic. * **Field Membership Problem:** Given two algebraic numbers $\alpha$, $\beta$, decide whether $\alpha \in \mathbb{Q}(\beta)$, and if so write $\alpha = f(\beta)$ for some $f(x) \in \mathbb{Q}[x]$. )Add)AlgebraicNumber)S)Dummy)sympify_sympify)sieve)dup_eval)QQ)_choose_factorminimal_polynomial)IsomorphismFailed)PolyPurePoly factor_list)public) MPContextc\|jj}|jj}||zdk7ry||k(ry|jj}|jj}d||z|dz}}} t|} | |z} | |kDr y|| zdzr|| zsy|dz }))z3Necessary but not sufficient test for isomorphism. rFT)minpolydegree discriminantr ) abnmdadbikhalfpPs g/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/sympy/polys/numberfields/subfield.pyis_isomorphism_possibler&3s A A1uzAv    !B    !BAqD"a%$qA  !H qD t8   !VqL26 Q c|jjr|jjs td|j}|jj |j }d|jj d}}}t}tddD]$}|jj|} |jj|} d| gtd|Dcgc]}| |z c}z| gz} ||_ |j| dd } | y| |k7r| }ny| dd D cgc]} t| | d z } } | d s| j| d stt| } t!| |j d }|j#|j%|j&r| cS|dz}'ycc}wcc} w) z2Construct field isomorphism using PSLQ algorithm. z)PSLQ doesn't support complex coefficientsdNrrld( i)maxcoeffmaxstepsr domain)rootis_realNotImplementedErrorrreplacegenrrrangeevalfdpspslqrpoplistreversedrcomposeremis_zero)rrfgrrprevctxr ABbasiscoeffschs r%field_isomorphism_pslqrIRs 66>>!"MNN A !%% Aaii&&($$qA +C 1a[( FFLLO FFLLOAq!6A1a4661"=%&4@ > > ; T>D 2 %,2#2;7a!A$vbz/77* JJL*hv&' t , 99Q<  A  & &M FAQ(T M7(8s ( G.G ct|j|\}}|D]\}}|jdk(s|jj }|j }t |dz g}}t|D])\} } |j| |j|| z zz+t|} |jj| |s|cSy)z/Construct field isomorphism via factorization.  extensionrN) rrrrepTC to_sympy_listlen enumerateappendr0r same_root) rr_factorsr?rGrFdtermsr coeffrs r%field_isomorphism_factorrZsQYY!4JAw1 88:? A__&F6{QuA%f- 45 U166AE?23 4U Ayy""1a( $ r'T)fastct|t|}}|js t|}|js t|}|j}|j}||k(r|j S|j j }|j j }|dk(r |jgS||zdk7ry|r t||}||S t||S#t$rYwxYw)a Find an embedding of one number field into another. Explanation =========== This function looks for an isomorphism from $\mathbb{Q}(a)$ onto some subfield of $\mathbb{Q}(b)$. Thus, it solves the Subfield Problem. Examples ======== >>> from sympy import sqrt, field_isomorphism, I >>> print(field_isomorphism(3, sqrt(2))) # doctest: +SKIP [3] >>> print(field_isomorphism( I*sqrt(3), I*sqrt(3)/2)) # doctest: +SKIP [2, 0] Parameters ========== a : :py:class:`~.Expr` Any expression representing an algebraic number. b : :py:class:`~.Expr` Any expression representing an algebraic number. fast : boolean, optional (default=True) If ``True``, we first attempt a potentially faster way of computing the isomorphism, falling back on a slower method if this fails. If ``False``, we go directly to the slower method, which is guaranteed to return a result. Returns ======= List of rational numbers, or None If $\mathbb{Q}(a)$ is not isomorphic to some subfield of $\mathbb{Q}(b)$, then return ``None``. Otherwise, return a list of rational numbers representing an element of $\mathbb{Q}(b)$ to which $a$ may be mapped, in order to define a monomorphism, i.e. an isomorphism from $\mathbb{Q}(a)$ to some subfield of $\mathbb{Q}(b)$. The elements of the list are the coefficients of falling powers of $b$. rrN) ris_AlgebraicNumberrto_primitive_elementrFrrr0rIr2rZ)rrr[rrresults r%field_isomorphismr`sZ 1:wqzqA   A    A   A  AAvxxz A AAvx1uz  +Aq1F! " $Aq ))#   s C)) C54C5c|jj}|j|d}|j||jdS)NT)frontr)rMinjectejectnewgens)r@Kfrephreps r%_switch_domainrjs> 55<<>D ::at: $D 55qvvay !!r'cH|jj\}}| |z SN)rMto_list)r#rGrVs r% _linsolverns 55==?DAq 2a4Kr'NF)expolysc T|s td|Dcgc] }t|}}|t|t}}nt dt }}d}|s|ddg}}t ||d} |ddD]l}|jr|jd!t| | \} } t| ||} | j\\} } } || |zz }|j| n|| } |s| j|fS|| |fS|ddg}}t ||d} tj| |f}|jg}|ddD].}|jr2|jd|j|j!|Bt ||d}tj||f}t| | \} } t| ||} | j\\} } } || |zz }|j| tj| |f}t#| |}t%|j'|}|j| |zz }|D cgc]} t)| j+||c} |gz}1|j,j.jrF|D cgc]} |j!| j0}} dgt3|z}||t } n|D cgc]} | j+}} || } |s| j||fS| ||fScc}wcc} wcc} wcc} w) a Find a single generator for a number field given by several generators. Explanation =========== The basic problem is this: Given several algebraic numbers $\alpha_1, \alpha_2, \ldots, \alpha_n$, find a single algebraic number $\theta$ such that $\mathbb{Q}(\alpha_1, \alpha_2, \ldots, \alpha_n) = \mathbb{Q}(\theta)$. This function actually guarantees that $\theta$ will be a linear combination of the $\alpha_i$, with non-negative integer coefficients. Furthermore, if desired, this function will tell you how to express each $\alpha_i$ as a $\mathbb{Q}$-linear combination of the powers of $\theta$. Examples ======== >>> from sympy import primitive_element, sqrt, S, minpoly, simplify >>> from sympy.abc import x >>> f, lincomb, reps = primitive_element([sqrt(2), sqrt(3)], x, ex=True) Then ``lincomb`` tells us the primitive element as a linear combination of the given generators ``sqrt(2)`` and ``sqrt(3)``. >>> print(lincomb) [1, 1] This means the primtiive element is $\sqrt{2} + \sqrt{3}$. Meanwhile ``f`` is the minimal polynomial for this primitive element. >>> print(f) x**4 - 10*x**2 + 1 >>> print(minpoly(sqrt(2) + sqrt(3), x)) x**4 - 10*x**2 + 1 Finally, ``reps`` (which was returned only because we set keyword arg ``ex=True``) tells us how to recover each of the generators $\sqrt{2}$ and $\sqrt{3}$ as $\mathbb{Q}$-linear combinations of the powers of the primitive element $\sqrt{2} + \sqrt{3}$. >>> print([S(r) for r in reps[0]]) [1/2, 0, -9/2, 0] >>> theta = sqrt(2) + sqrt(3) >>> print(simplify(theta**3/2 - 9*theta/2)) sqrt(2) >>> print([S(r) for r in reps[1]]) [-1/2, 0, 11/2, 0] >>> print(simplify(-theta**3/2 + 11*theta/2)) sqrt(3) Parameters ========== extension : list of :py:class:`~.Expr` Each expression must represent an algebraic number $\alpha_i$. x : :py:class:`~.Symbol`, optional (default=None) The desired symbol to appear in the computed minimal polynomial for the primitive element $\theta$. If ``None``, we use a dummy symbol. ex : boolean, optional (default=False) If and only if ``True``, compute the representation of each $\alpha_i$ as a $\mathbb{Q}$-linear combination over the powers of $\theta$. polys : boolean, optional (default=False) If ``True``, return the minimal polynomial as a :py:class:`~.Poly`. Otherwise return it as an :py:class:`~.Expr`. Returns ======= Pair (f, coeffs) or triple (f, coeffs, reps), where: ``f`` is the minimal polynomial for the primitive element. ``coeffs`` gives the primitive element as a linear combination of the given generators. ``reps`` is present if and only if argument ``ex=True`` was passed, and is a list of lists of rational numbers. Each list gives the coefficients of falling powers of the primitive element, to recover one of the original, given generators. z4Cannot compute primitive element for empty extensionNxcX|j\}}|jdkr| }|S)Nr) primitiveLC)r?rTs r% _canonicalizez(primitive_element.._canonicalize^s*{{}1 446A:Ar'rrTrprKr.) ValueErrorrrrrrr is_RationalrRrr sqf_normas_exprr algebraic_fieldunitconvertrjrngcdr rmextr0rMrP)rLrrrorprclsrvr4rFr@rTrUsr?rgrepsr#LrHerepogenHs r%primitive_elementrsf OPP*343#4I4}T3sX3 lQCV sAT 2QR= C a $Q#6JAww3/A ICQA 1S5LC MM!   ! 99;& &q66> !A,C3.A As8$A FF8D}G ?? MM!  KK # '  sAT 2   3x ( 1- 7 7As +JJL Q qu  a   3x ( 1a q"vv$8<=1dA.=F!G$ uuzz'0 1!QYYq\   1 1S^# " "& 'QQYY[ ' 'aA yy{FA%%&!|C5h> 2 (sL"L"L L%r4aliasct|dr t|}n|g}t|dk(r#t|dtrt |d|St ||d\}}tdt||D}|t ||f|St|}|jst |||}t||}|t |||St|d |j) a Express one algebraic number in the field generated by another. Explanation =========== Given two algebraic numbers $\eta, \theta$, this function either expresses $\eta$ as an element of $\mathbb{Q}(\theta)$, or else raises an exception if $\eta \not\in \mathbb{Q}(\theta)$. This function is essentially just a convenience, utilizing :py:func:`~.field_isomorphism` (our solution of the Subfield Problem) to solve this, the Field Membership Problem. As an additional convenience, this function allows you to pass a list of algebraic numbers $\alpha_1, \alpha_2, \ldots, \alpha_n$ instead of $\eta$. It then computes $\eta$ for you, as a solution of the Primitive Element Problem, using :py:func:`~.primitive_element` on the list of $\alpha_i$. Examples ======== >>> from sympy import sqrt, to_number_field >>> eta = sqrt(2) >>> theta = sqrt(2) + sqrt(3) >>> a = to_number_field(eta, theta) >>> print(type(a)) >>> a.root sqrt(2) + sqrt(3) >>> print(a) sqrt(2) >>> a.coeffs() [1/2, 0, -9/2, 0] We get an :py:class:`~.AlgebraicNumber`, whose ``.root`` is $\theta$, whose value is $\eta$, and whose ``.coeffs()`` show how to write $\eta$ as a $\mathbb{Q}$-linear combination in falling powers of $\theta$. Parameters ========== extension : :py:class:`~.Expr` or list of :py:class:`~.Expr` Either the algebraic number that is to be expressed in the other field, or else a list of algebraic numbers, a primitive element for which is to be expressed in the other field. theta : :py:class:`~.Expr`, None, optional (default=None) If an :py:class:`~.Expr` representing an algebraic number, behavior is as described under **Explanation**. If ``None``, then this function reduces to a shorthand for calling :py:func:`~.primitive_element` on ``extension`` and turning the computed primitive element into an :py:class:`~.AlgebraicNumber`. gen : :py:class:`~.Symbol`, None, optional (default=None) If provided, this will be used as the generator symbol for the minimal polynomial in the returned :py:class:`~.AlgebraicNumber`. alias : str, :py:class:`~.Symbol`, None, optional (default=None) If provided, this will be used as the alias symbol for the returned :py:class:`~.AlgebraicNumber`. Returns ======= AlgebraicNumber Belonging to $\mathbb{Q}(\theta)$ and equaling $\eta$. Raises ====== IsomorphismFailed If $\eta \not\in \mathbb{Q}(\theta)$. See Also ======== field_isomorphism primitive_element __iter__rr)rTrwc3,K|] \}}||zywrl).0rXrs r% z"to_number_field..sBZUCuSyBsrz is not in a subfield of )hasattrr:rP isinstancetuplerrsumziprr]r`rr0)rLthetar4rrrFr0s r%to_number_fieldrs`y*%O K  9~z)A,>y|599' 3dCOGV B3vy+AB BD }e<<''#Es%@E"4/  "5&> >#37DF Fr'rl)'__doc__sympy.core.addrsympy.core.numbersrsympy.core.singletonrsympy.core.symbolrsympy.core.sympifyrr sympy.ntheoryr sympy.polys.densetoolsr sympy.polys.domainsr sympy.polys.numberfields.minpolyr r sympy.polys.polyerrorsrsympy.polys.polytoolsrrrsympy.utilitiesrmpmathrr&rIrZr`rjrnrrrr'r%rs D."#0+"O4==">5p0$(L*L*^" UuEUUphF$dhFhFr'