a
    <b?_                     @   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 ddlmZmZ dd	lmZ dd
lmZ ddlmZmZ ddlmZ ddlmZmZ ddlmZmZ dd ZG dd deZ dd Z!edd Z"d%ddZ#dd Z$dd Z%dd  Z&d!d" Z'ed&d#d$Z(dS )'zPrime ideals in number fields.     )Expr)Poly)FF)QQ)ZZ)DomainMatrix)CoercionFailedGeneratorsNeeded)IntegerPowerable)public   )	round_twonilradical_mod_p)StructureError)ModuleEndomorphismfind_min_poly)coeff_searchsupplement_a_subspacec                 C   sH   d}d}|   sd}n|  s$d}n|  s0d}|durDt|| dS )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.zhave 1 as its first generator.z<have square matrix, of maximal rank, in Hermite Normal Form.)Zis_power_basis_submodulestarts_with_unityZis_sq_maxrank_HNFr   )	submoduleprefixZcond r   o/Users/vegardjervell/Documents/master/model/venv/lib/python3.9/site-packages/sympy/polys/numberfields/primes.py*_check_formal_conditions_for_maximal_order   s    r   c                   @   s~   e Zd ZdZdddZdddZdd	 Zd
d Zdd Zdd Z	e	Z
dd ZeZdd Zdd Zdd Zdd ZdddZdS )
PrimeIdealz8
    A prime ideal in a ring of algebraic integers.
    Nc                 C   sF   t | || _|| _|| _|| _d| _|dur2|n| || | _dS )a  
        Parameters
        ==========

        ZK : :py:class:`~.Submodule`
            The maximal order where this ideal lives.
        p : int
            The rational prime this ideal divides.
        alpha : :py:class:`~.PowerBasisElement`
            Such that the ideal is equal to ``p*ZK + alpha*ZK``.
        f : int
            The inertia degree.
        e : int, ``None``, optional
            The ramification index, if already known. If ``None``, we will
            compute it here.

        N)r   ZKpalphaf_test_factor	valuatione)selfr   r   r   r   r!   r   r   r   __init__/   s    zPrimeIdeal.__init__Fc           	      C   s   |p| j jjj}| j| j| j| jf\}}}}t|j	|d
 }|jdkr\d| d|j }d| d| d}|rv|S d| d| d	| d
S )a  
        Print a representation of this prime ideal.

        Examples
        ========

        >>> 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]._pretty())
        [ (11, x**3 + 5*x**2 + 4*x - 1) e=1, f=3 ]
        >>> print(P[0]._pretty(field_gen=zeta))
        [ (11, zeta**3 + 5*zeta**2 + 4*zeta - 1) e=1, f=3 ]
        >>> print(P[0]._pretty(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   (z)/z, )z[ z e=z, f=z ])r   parentTgenr   r   r!   r   str	numeratoras_exprdenom)	r"   Z	field_genZ	just_gensr   r   r!   r   Z	alpha_repgensr   r   r   _prettyI   s    !
zPrimeIdeal._prettyc                 C   s   |   S N)r0   r"   r   r   r   __repr__t   s    zPrimeIdeal.__repr__c                 C   s(   | j | j | j| j  }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   Z_starts_with_unityZ_is_sq_maxrank_HNF)r"   Mr   r   r   as_submodulew   s    7zPrimeIdeal.as_submodulec                 C   s   t |tr|  | kS tS r1   )
isinstancer   r5   NotImplementedr"   otherr   r   r   __eq__   s    
zPrimeIdeal.__eq__c                 C   s   |   | S )z
        Convert to a :py:class:`~.Submodule` and add to another
        :py:class:`~.Submodule`.

        See Also
        ========

        as_submodule

        r5   r8   r   r   r   __add__   s    zPrimeIdeal.__add__c                 C   s   |   | S )z
        Convert to a :py:class:`~.Submodule` and multiply by another
        :py:class:`~.Submodule` or a rational number.

        See Also
        ========

        as_submodule

        r;   r8   r   r   r   __mul__   s    zPrimeIdeal.__mul__c                 C   s   | j S r1   )r   r2   r   r   r   _zeroth_power   s    zPrimeIdeal._zeroth_powerc                 C   s   | S r1   r   r2   r   r   r   _first_power   s    zPrimeIdeal._first_powerc                 C   s&   | j du r t| j| jg| j| _ | j S )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.
        N)r   _compute_test_factorr   r   r   r2   r   r   r   test_factor   s    
zPrimeIdeal.test_factorc                 C   s
   t || 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"   Ir   r   r   r       s    zPrimeIdeal.valuationc              
   C   s   t |trbzt|}W n< tyR } z$|du r4|dt||}W Y d}~n
d}~0 0 | | S t |tr|jr| j|j	}|dkr|
|}|| jS tdS )a  
        Reduce a univariate :py:class:`~.Poly` *f*, or an :py:class:`~.Expr`
        expressing the same, modulo this :py:class:`~.PrimeIdeal`.

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

        If our second generator $\alpha$ is zero, then we simply reduce the
        coefficients of *f* mod the rational prime $p$ lying under this ideal.

        Otherwise we first reduce *f* mod $\alpha$ (as a polynomial in the same
        variable as *f*), and then mod $p$.

        Examples
        ========

        >>> from sympy import QQ, cyclotomic_poly, symbols
        >>> zeta = symbols('zeta')
        >>> Phi = cyclotomic_poly(7, zeta)
        >>> k = QQ.algebraic_field((Phi, zeta))
        >>> P = k.primes_above(11)
        >>> frp = P[0]
        >>> B = k.integral_basis(fmt='sympy')
        >>> print([frp._reduce_poly(b, zeta) for b in B])
        [1, zeta, zeta**2, -5*zeta**2 - 4*zeta + 1, -zeta**2 - zeta - 5,
         4*zeta**2 - zeta - 1]

        Parameters
        ==========

        f : :py:class:`~.Poly`, :py:class:`~.Expr`
            The univariate polynomial to be reduced.

        gen : :py:class:`~.Symbol`, None, optional (default=None)
            Symbol to use as the variable in the polynomials. If *f* is a
            :py:class:`~.Poly` or a non-constant :py:class:`~.Expr`, this
            replaces its variable. If *f* is a constant :py:class:`~.Expr`,
            then *gen* must be supplied.

        Returns
        =======

        :py:class:`~.Poly`, :py:class:`~.Expr`
            Type is same as that of given *f*. If returning a
            :py:class:`~.Poly`, its domain will be the finite field
            $\mathbb{F}_p$.

        Raises
        ======

        GeneratorsNeeded
            If *f* is a constant :py:class:`~.Expr` and *gen* is ``None``.
        NotImplementedError
            If *f* is other than :py:class:`~.Poly` or :py:class:`~.Expr`,
            or is not univariate.

        Nr   )r6   r   r   r	   _reduce_polyr-   Zis_univariater   Zpolyr*   remZset_modulusr   NotImplementedError)r"   r   r*   gr!   ar   r   r   rD     s    :
 
zPrimeIdeal._reduce_poly)N)NF)N)__name__
__module____qualname____doc__r#   r0   r3   r5   r:   r<   __radd__r=   __rmul__r>   r?   rA   r    rD   r   r   r   r   r   *   s   

+=r   c                    sr   t | |   fdd|D }td|jftj| }| dddf  }|j	|j
| |jd}|S )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.)

    c                    s   g | ]}  |jd qS )modulus)Zinner_endomorphismmatrix.0rG   Er   r   r   
<listcomp>m      z(_compute_test_factor.<locals>.<listcomp>r   Nr.   )r   Zendomorphism_ringr   Zzerosnr   ZvstackZ	nullspaceZ	transposer(   rQ   r.   )r   r/   r   ZmatricesBr%   betar   rT   r   r@   M  s    r@   c                 C   sf  |j |j }}|j|j|j  }}}|t | j | | j }|t}|	 }|| dkrddS |
 }	|| |	  }
|
| dk}d}|| }t|D ]R}|j|dd|f |d}||	9 }|| }t|D ]}|| |||f< qq||d |d f j| dkrqb|| }|rNz|t}W n tyJ   Y qbY n0 n
|t}|d7 }q|S )au  
    Compute the *P*-adic valuation for an integral ideal *I*.

    Examples
    ========

    >>> from sympy import QQ
    >>> from sympy.abc import theta
    >>> from sympy.polys import cyclotomic_poly
    >>> from sympy.polys.numberfields import prime_valuation
    >>> T = cyclotomic_poly(5)
    >>> K = QQ.algebraic_field((T, theta))
    >>> 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.)

    r   NrX   r   )r   r   rY   rQ   r.   
convert_tor   invr   detrA   ranger(   Z	representZflatelementr   )rC   Pr   r   rY   WdADr[   r   Zneed_complete_testvjcir   r   r   rB   {  s:    -
 

rB   Nc                    s   t | |j}|j}t fdd| D r2| S |du r`|durL | }nt|| j }|	 } fdd|dd D }|| 7 }t
t|d}	|	D ]B}
tdd t|
|D }||| }|  dkr|    S qdS )	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.)

    c                 3   s   | ]}|   d V  qdS )r   N)equivrR   r   r   r   	<genexpr>  rW   z_two_elt_rep.<locals>.<genexpr>Nc                    s   g | ]} | qS r   r   rS   Zomrk   r   r   rV     rW   z _two_elt_rep.<locals>.<listcomp>r   c                 s   s   | ]\}}|| V  qd S r1   r   )rS   ciZbetair   r   r   rl     rW   r   )r   r(   r)   allZzeroabsZsubmodule_from_gensrQ   r^   Zbasis_element_pullbacksr   lensumzipZnorm)r/   r   r   r   ZNpZpbr)   omegar[   searchrh   r   rY   r   rk   r   _two_elt_rep  s$    (
rv   c                    s4    j j}t|d}| \}} fdd|D S )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``.
    rO   c                    s4   g | ],\}}t   jt|td | |qS domain)r   r(   Zelement_from_polyr   r   Zdegree)rS   tr!   r   r   r   r   rV   '  s
   z+_prime_decomp_easy_case.<locals>.<listcomp>)r(   r)   r   factor_list)r   r   r)   ZT_barlcflr   r{   r   _prime_decomp_easy_case  s    r   c           
         s   | j }|j\}}|dkr&||t}n|||tdddf }|jd |k rjt|t t}||}|	  |
|}t| fdd}|j d}	|	 sJ |	|fS )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).

    r   Nr   c                    s   |   |  S r1   r   r$   rk   r   r   <lambda>\  rW   z._prime_decomp_compute_kernel.<locals>.<lambda>rO   )rQ   shapeZeyer   hstackr   r\   r   submodule_from_matrixZcompute_mult_tabZdiscard_beforer   Zkernelr   )
rC   r   r   rb   rY   rrZ   GphiNr   rk   r   _prime_decomp_compute_kernel-  s    


r   c                    s\   | j j\}}|| }j | j    fddt jd D }t|||d}t|||S )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

    c                    s(   g | ] }j  d d |f jdqS )NrX   )r(   r.   )rS   rg   r   r   r   r   rV   z  rW   z/_prime_decomp_maximal_ideal.<locals>.<listcomp>r   )r   )rQ   r   r_   rv   r   )rC   r   r   mrY   r   r/   r   r   r   r   _prime_decomp_maximal_idealb  s    r   c                    sP  | j |kr|j |u r|j |u s"J |d }|j|u s<J g t|td}| \}}|d d }	||	}
|	|
\}}}|dksJ tt	t
||	 tdjj t fddtt D }d| }||g}g }|D ]f}| j|u sJ | jtjfdd| D  }| t}||}|| q|S )	z
    Perform the step in the prime decomposition algorithm where we have determined
    the 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   )Zpowersr   rx   c                 3   s   | ]} | |  V  qd S r1   r   )rS   ri   )rU   alpha_powersr   r   rl     rW   z,_prime_decomp_split_ideal.<locals>.<genexpr>c                    s    g | ]} | j td qS rw   )columnr   rm   )r!   r   r   r   rV     s   z-_prime_decomp_split_ideal.<locals>.<listcomp>)r(   Z	to_parentmoduler   r   r|   ZquoZgcdexlistreversedr   r   reprr   r_   rq   rQ   r\   r   Zbasis_elementsZcolumnspacer   append)rC   r   r   r   r   r   r   r}   r~   m1m2UVrG   Zeps1Zeps2ZidempsZfactorsZepsre   rb   Hr   )rU   r   r!   r   r   _prime_decomp_split_ideal  s2    "
 
r   c                 C   s  |du r|du rt d|dur(t| |du r8|jj}i }|du sL|du r\t||d\}}| }|| }||  dkrt| |S |p|| pt|| }|g}g }	|r|	 }
t
|
| |\}}|jdkrt|
| |}|	| qt|
| |||\}}|||g q|	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.)

    Nz)At least one of T or ZK must be provided.)radicalsr   r   )
ValueErrorr   r(   r)   r   Zdiscriminantr   getr   popr   rY   r   r   r   extend)r   r)   r   ZdKradicalr   ZdTZ	f_squaredstackZprimesrC   r   r   ra   ZI1ZI2r   r   r   prime_decomp  s2    7

r   )NN)NNNN))rL   Zsympy.core.exprr   Zsympy.polys.polytoolsr   Zsympy.polys.domains.finitefieldr   Z!sympy.polys.domains.rationalfieldr   Zsympy.polys.domains.integerringr   Z!sympy.polys.matrices.domainmatrixr   Zsympy.polys.polyerrorsr   r	   Zsympy.polys.polyutilsr
   Zsympy.utilities.decoratorr   Zbasisr   r   
exceptionsr   modulesr   r   Z	utilitiesr   r   r   r   r@   rB   rv   r   r   r   r   r   r   r   r   r   <module>   s6     %.
[
E5*