U
    	Ç-eE   ã                   @   sŒ   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZmZmZ dd	lmZ d
d„ Zddd„Zdd„ Ze
ddd„ƒZdS )z,Computing integral bases for number fields. é    )ÚPoly)ÚAlgebraicField)ÚZZ)ÚQQ)Úpublicé   )ÚModuleEndomorphismÚModuleHomomorphismÚ
PowerBasis)Ú extract_fundamental_discriminantc                 C   s¾   | j }t| |d}| ¡ \}}|dks*t‚td||d}|D ]\}}||9 }q<|| }	t|td}
t|	td}|
| |  | }t||d}|}||	fD ]}| |¡}q–|| }| ¡ }||fS )zz
    Apply the "Dedekind criterion" to test whether the order needs to be
    enlarged relative to a given prime *p*.
    ©Úmodulusr   ©Údomain)Úgenr   Zfactor_listÚAssertionErrorr   ÚgcdÚdegree)ÚTÚpÚxZT_barÚlcÚflZg_barZti_barÚ_Zh_barÚgÚhÚfZf_barZZ_barÚbÚU_barÚm© r    ú_/var/www/html/Darija-Ai-Train/env/lib/python3.8/site-packages/sympy/polys/numberfields/basis.pyÚ_apply_Dedekind_criterion   s$    
r"   Nc                    sB   | j }ˆ dkr$|‰ ˆ |k r$ˆ |9 ‰ qt| ‡ fdd„ƒ}|j|dS )aþ  
    Compute the nilradical mod *p* for a given order *H*, and prime *p*.

    Explanation
    ===========

    This is the ideal $I$ in $H/pH$ consisting of all elements some positive
    power of which is zero in this quotient ring, i.e. is a multiple of *p*.

    Parameters
    ==========

    H : :py:class:`~.Submodule`
        The given order.
    p : int
        The rational prime.
    q : int, optional
        If known, the smallest power of *p* that is $>=$ the dimension of *H*.
        If not provided, we compute it here.

    Returns
    =======

    :py:class:`~.Module` representing the nilradical mod *p* in *H*.

    References
    ==========

    .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory*.
    (See Lemma 6.1.6.)

    Nc                    s   | ˆ  S ©Nr    ©r   ©Úqr    r!   Ú<lambda>K   ó    z"nilradical_mod_p.<locals>.<lambda>r   )Únr   Úkernel)ÚHr   r&   r)   Úphir    r%   r!   Únilradical_mod_p%   s    !
r-   c           
         sŠ   t | ||d}| jj| j|j | jd}|||   }| ¡ ‰ t| ˆ ‡ fdd„ƒ}|j|d}| jj| j|j | j| d}||  }	|	|fS )zD
    Perform the second enlargement in the Round Two algorithm.
    r%   )Údenomc                    s
   ˆ   | ¡S r#   )Zinner_endomorphismr$   ©ÚEr    r!   r'   W   r(   z%_second_enlargement.<locals>.<lambda>r   )r-   ÚparentZsubmodule_from_matrixÚmatrixr.   Zendomorphism_ringr	   r*   )
r+   r   r&   ZIpÚBÚCr,   ÚgammaÚGÚH1r    r/   r!   Ú_second_enlargementO   s    r8   c                 C   sŠ  d}t | tƒr| | j ¡  }} | jr8| jr8| jttfkr@t	dƒ‚|  
¡ \} }|  ¡ }|  ¡ }t t|ƒ¡}t|ƒ\}}t|p~| ƒ}| ¡ }	d}
|r4| ¡ \}}t| |ƒ\}}|dkr¸qŽ| t|td¡}|	j|| |	 |d}	||krêqŽ|}||k r||9 }qît|	||ƒ\}}
||	krŽ|}	t|	||ƒ\}}
qqŽ|
dk	rRt |tƒrR|
||< |	}d|_d|_||j ¡ d  |jd|   }||fS )a  
    Zassenhaus's "Round 2" algorithm.

    Explanation
    ===========

    Carry out Zassenhaus's "Round 2" algorithm on an irreducible polynomial
    *T* over :ref:`ZZ` or :ref:`QQ`. This computes an integral basis and the
    discriminant for the field $K = \mathbb{Q}[x]/(T(x))$.

    Alternatively, you may pass an :py:class:`~.AlgebraicField` instance, in
    place of the polynomial *T*, in which case the algorithm is applied to the
    minimal polynomial for the field's primitive element.

    Ordinarily this function need not be called directly, as one can instead
    access the :py:meth:`~.AlgebraicField.maximal_order`,
    :py:meth:`~.AlgebraicField.integral_basis`, and
    :py:meth:`~.AlgebraicField.discriminant` methods of an
    :py:class:`~.AlgebraicField`.

    Examples
    ========

    Working through an AlgebraicField:

    >>> from sympy import Poly, QQ
    >>> from sympy.abc import x
    >>> T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
    >>> K = QQ.alg_field_from_poly(T, "theta")
    >>> print(K.maximal_order())
    Submodule[[2, 0, 0], [0, 2, 0], [0, 1, 1]]/2
    >>> print(K.discriminant())
    -503
    >>> print(K.integral_basis(fmt='sympy'))
    [1, theta, theta/2 + theta**2/2]

    Calling directly:

    >>> from sympy import Poly
    >>> from sympy.abc import x
    >>> from sympy.polys.numberfields.basis import round_two
    >>> T = Poly(x ** 3 + x ** 2 - 2 * x + 8)
    >>> print(round_two(T))
    (Submodule[[2, 0, 0], [0, 2, 0], [0, 1, 1]]/2, -503)

    The nilradicals mod $p$ that are sometimes computed during the Round Two
    algorithm may be useful in further calculations. Pass a dictionary under
    `radicals` to receive these:

    >>> T = Poly(x**3 + 3*x**2 + 5)
    >>> rad = {}
    >>> ZK, dK = round_two(T, radicals=rad)
    >>> print(rad)
    {3: Submodule[[-1, 1, 0], [-1, 0, 1]]}

    Parameters
    ==========

    T : :py:class:`~.Poly`, :py:class:`~.AlgebraicField`
        Either (1) the irreducible polynomial over :ref:`ZZ` or :ref:`QQ`
        defining the number field, or (2) an :py:class:`~.AlgebraicField`
        representing the number field itself.

    radicals : dict, optional
        This is a way for any $p$-radicals (if computed) to be returned by
        reference. If desired, pass an empty dictionary. If the algorithm
        reaches the point where it computes the nilradical mod $p$ of the ring
        of integers $Z_K$, then an $\mathbb{F}_p$-basis for this ideal will be
        stored in this dictionary under the key ``p``. This can be useful for
        other algorithms, such as prime decomposition.

    Returns
    =======

    Pair ``(ZK, dK)``, where:

        ``ZK`` is a :py:class:`~sympy.polys.numberfields.modules.Submodule`
        representing the maximal order.

        ``dK`` is the discriminant of the field $K = \mathbb{Q}[x]/(T(x))$.

    See Also
    ========

    .AlgebraicField.maximal_order
    .AlgebraicField.integral_basis
    .AlgebraicField.discriminant

    References
    ==========

    .. [1] Cohen, H. *A Course in Computational Algebraic Number Theory.*

    NzDRound 2 requires an irreducible univariate polynomial over ZZ or QQ.r   r   )Zhnf_modulusTé   )Ú
isinstancer   ÚextZminpoly_of_elementZis_univariateZis_irreducibler   r   r   Ú
ValueErrorZ)make_monic_over_integers_by_scaling_rootsr   ZdiscriminantZ
from_sympyÚabsr   r
   Zwhole_submoduleÚpopitemr"   Zelement_from_polyr   Úaddr8   ÚdictZ_starts_with_unityZ_is_sq_maxrank_HNFr2   Zdetr.   )r   ZradicalsÚKr   r)   ÚDZ	D_modulusÚFZZthetar+   Znilradr   Úer   r   ÚUr&   r7   ZZKZdKr    r    r!   Ú	round_two^   sP    `
ÿþ

 rF   )N)N)Ú__doc__Zsympy.polys.polytoolsr   Z"sympy.polys.domains.algebraicfieldr   Zsympy.polys.domains.integerringr   Z!sympy.polys.domains.rationalfieldr   Zsympy.utilities.decoratorr   Úmodulesr   r	   r
   Z	utilitiesr   r"   r-   r8   rF   r    r    r    r!   Ú<module>   s   
*