U
    ZÊ¹j¿P  ã                   @   s@  d Z ddlmZ ddlZddlmZ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mZmZmZ ddlmZ ddlmZmZmZmZ ddl m!Z! ddl"m#Z# G dd„ deƒZ$d)dd„Z%dd„ Z&d*dd„Z'd+dd„Z(d,dd„Z)d-d d!„Z*d.d"d#„Z+d/d$d%„Z,e#dddd&œd'd(„ƒZ-dS )0zà
Compute Galois groups of polynomials.

We use algorithms from [1], with some modifications to use lookup tables for
resolvents.

References
==========

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

é    )ÚdefaultdictN)ÚDummyÚsymbols)Ú	is_square©ÚZZ)Ú
dup_random)Údup_eval)Údup_discriminant)Údup_factor_listÚdup_irreducible_p)ÚGaloisGroupExceptionÚget_resolvent_by_lookupÚdefine_resolventsÚ	Resolvent)Úcoeff_search)ÚPolyÚpoly_from_exprÚPolificationFailedÚComputationFailed)Ú	dup_sqf_p)Úpublicc                   @   s   e Zd ZdS )ÚMaxTriesExceptionN)Ú__name__Ú
__module__Ú__qualname__© r   r   úd/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/polys/numberfields/galoisgroups.pyr   #   s   r   é
   é   Tc                    sR  t dƒ}|  ¡ }|dkrtƒ }| | j¡ |r:i ‰ d}d}‡ fdd„}	t|ƒD ]ú}
|rÐ|	|ƒ}t|ƒ}tdd„ |D ƒƒ}|| |kr¶|dkrž|d	7 }|d	 }n|d	8 }|	|ƒ}t|ƒ}td	ƒgd
d„ |D ƒ }n2t	|
d d	 |ƒ}t
 d|d	 ¡}t|| |tƒ}t|| jƒ}t|  || ¡|ƒ}|j|krNt|j ¡ tƒrN||f  S qNt‚dS )a  
    Given a univariate, monic, irreducible polynomial over the integers, find
    another such polynomial defining the same number field.

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

    See Alg 6.3.4 of [1].

    Parameters
    ==========

    T : Poly
        The given polynomial
    max_coeff : int
        When choosing a transformation as part of the process,
        keep the coeffs between plus and minus this.
    max_tries : int
        Consider at most this many transformations.
    history : set, None, optional (default=None)
        Pass a set of ``Poly.rep``'s in order to prevent any of these
        polynomials from being returned as the polynomial ``U`` i.e. the
        transformation of the given polynomial *T*. The given poly *T* will
        automatically be added to this set, before we try to find a new one.
    fixed_order : bool, default True
        If ``True``, work through candidate transformations A(x) in a fixed
        order, from small coeffs to large, resulting in deterministic behavior.
        If ``False``, the A(x) are chosen randomly, while still working our way
        up from small coefficients to larger ones.

    Returns
    =======

    Pair ``(A, U)``

        ``A`` and ``U`` are ``Poly``, ``A`` is the
        transformation, and ``U`` is the transformed polynomial that defines
        the same number field as *T*. The polynomial ``A`` maps the roots of
        *T* to the roots of ``U``.

    Raises
    ======

    MaxTriesException
        if could not find a polynomial before exceeding *max_tries*.

    ÚXNé   é   c                    s   ˆ   | t| dƒ¡}|ˆ | < |S )Né   )Úgetr   )ÚdegreeÚgen©Zcoeff_generatorsr   r   Úget_coeff_generatorc   s    z9tschirnhausen_transformation.<locals>.get_coeff_generatorc                 s   s   | ]}t |ƒV  qd S )N)Úabs©Ú.0Úcr   r   r   Ú	<genexpr>x   s     z/tschirnhausen_transformation.<locals>.<genexpr>r#   c                 S   s   g | ]}t |ƒ‘qS r   r   r*   r   r   r   Ú
<listcomp>�   s     z0tschirnhausen_transformation.<locals>.<listcomp>é   )r   r%   ÚsetÚaddÚrepÚrangeÚnextÚmaxr   ÚminÚrandomÚrandintr   r   r&   Z	resultantr   Zto_listr   )ÚTZ	max_coeffÚ	max_triesÚhistoryÚfixed_orderr    ÚnZdeg_coeff_sumZcurrent_degreer(   Úir&   ZcoeffsÚmÚaÚCÚdÚAÚUr   r'   r   Útschirnhausen_transformation'   s>    1
rE   c                 C   s$   t | tƒr|  ¡ nt| tƒ}t|ƒS )z?Convenience to check if a Poly or dup has square discriminant. )Ú
isinstancer   Zdiscriminantr
   r   r   )r9   rB   r   r   r   Úhas_square_disc’   s    rG   Fc                 C   s(   ddl m} t| ƒr|jdfS |jdfS )z~
    Compute the Galois group of a polynomial of degree 3.

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

    Uses Prop 6.3.5 of [1].

    r   )ÚS3TransitiveSubgroupsTF)Úsympy.combinatorics.galoisrH   rG   ZA3ÚS3)r9   r:   Ú	randomizerH   r   r   r   Ú_galois_group_degree_3˜   s    
ÿrL   c                    s  ddl m} ddlm} tdƒ}|d |d  |d |d   }|dƒ|dƒddƒ|dƒddƒg}t|||ƒ}|d |d d  |d |d d   |d |d d   |d |d d   }	|dƒ|dƒddƒg}
tƒ }t|ƒD �]}|dk�rt| ||| d�\}} |j	| d	d
�\}}}t
|tƒ�s*qât| ƒ}|dk�rZ|�rL|jd	fn|jdf  S |�rn|jd	f  S || ‰ |	jt|ˆ |ƒƒd	d�}‡ fdd„|
D ƒ}t|||ƒ}| 	| ¡\}}}t|tƒ}|dk�rÒqât|ƒ�rê|jdf  S |jdf  S qât‚dS )zª
    Compute the Galois group of a polynomial of degree 4.

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

    Follows Alg 6.3.7 of [1], using a pure root approximation approach.

    r   ©ÚPermutation©ÚS4TransitiveSubgroupszX0 X1 X2 X3r"   r#   r!   ©r:   r;   r<   T)Zfind_integer_rootNF©Zsimultaneousc                    s   g | ]}ˆ | ˆ  ‘qS r   r   ©r+   Útau©Úsigmar   r   r.   ï   s     z6_galois_group_degree_4_root_approx.<locals>.<listcomp>)Ú sympy.combinatorics.permutationsrN   rI   rP   r   r   r0   r3   rE   Úeval_for_polyr   r   rG   ÚA4ÚS4ÚVÚsubsÚzipr
   r   ÚC4ÚD4r   )r9   r:   rK   rN   rP   r    ZF1Ús1ZR1ÚF2_preÚs2_prer;   r>   Ú_ÚR_dupÚi0Úsq_discÚF2Ús2ÚR2rB   r   rU   r   Ú"_galois_group_degree_4_root_approx§   sT    
 ýPþ
þ

ÿ


rj   c           
      C   sè   ddl m} tƒ }t|ƒD ]2}t| dƒ}t|tƒr6 qRt| ||| d�\}} qt‚t	|tƒ}t
tdd„ |d D ƒg ƒƒ}	|	dgkržt| ƒr”|jdfS |jd	fS |	ddd
gkr¶|jd	fS |	dddgkrÎ|jdfS |	dd
gksÞt‚|jd	fS )z¢
    Compute the Galois group of a polynomial of degree 4.

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

    Based on Alg 6.3.6 of [1], but uses resolvent coeff lookup.

    r   rO   rQ   c                 S   s"   g | ]\}}t |ƒd  g| ‘qS )r#   ©Úlen)r+   ÚrÚer   r   r   r.     s    z1_galois_group_degree_4_lookup.<locals>.<listcomp>r#   é   TFé   r"   )rI   rP   r0   r3   r   r   r   rE   r   r   ÚsortedÚsumrG   rY   rZ   r^   r[   ÚAssertionErrorr_   )
r9   r:   rK   rP   r;   r>   rd   rc   ÚflÚLr   r   r   Ú_galois_group_degree_4_lookupþ   s6    


þ

ÿþ
ÿ

rv   c                    s(  ddl m} ddlm} tdƒ}tƒ }|d \}}}	|j|Ž }t|||	ƒ}
tƒ }d}t	|ƒD �]À}|dkr€t
| ||| d�\}} t| dƒ}t|tƒs–q\|sÚt| ƒ}t|tƒrÈ|rº|jd	fn|jdf  S |sÚ|jdf  S d	}|
 | ¡}| ¡ D ]\}}t||tƒsð �qqð|}|d |d d
  |d |d
 d
   |d
 |d d
   |d |d d
   |d |d d
   }|dƒ|dƒddƒd
dƒg}|}|	| ‰ |jt|ˆ |ƒƒd	d�}‡ fdd„|D ƒ}t|||ƒ}| | ¡\}}}t|tƒ}|dk�røq\t|ƒ�r|jd	f  S |jd	f  S q\t‚dS )zÜ
    Compute the Galois group of a polynomial of degree 5.

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

    Based on Alg 6.3.9 of [1], but uses a hybrid approach, combining resolvent
    coeff lookup, with root approximation.

    r   ©ÚS5TransitiveSubgroupsrM   zX0,X1,X2,X3,X4)r/   r#   FrQ   r#   Tr"   r!   rp   rR   c                    s   g | ]}ˆ | ˆ  ‘qS r   r   rS   rU   r   r   r.   k  s     z1_galois_group_degree_5_hybrid.<locals>.<listcomp>N)rI   rx   rW   rN   r   r   Zas_exprr   r0   r3   rE   r   r   r   rG   r   ÚA5ÚS5ÚM20Z round_roots_to_integers_for_polyÚitemsr	   r\   r]   rX   r
   r   ÚC5ÚD5r   )r9   r:   rK   rx   rN   ZX5ÚresZF51rc   Zs51ZR51r;   Zreached_second_stager>   ZR51_duprf   Zrounded_rootsZpermutation_indexZcandidate_rootr    ra   rb   re   rg   rh   ri   rd   rB   r   rU   r   Ú_galois_group_degree_5_hybrid)  sb    
þ



ÿ
dþ


r€   c                 C   sÌ   ddl m} | }tƒ }t|ƒD ]2}t| dƒ}t|tƒr: qVt| ||| d�\}} qt‚t	| ƒ}	t
|tƒr€|	rv|jdfS |jdfS |	sŽ|jdfS t|t |¡d� ¡ d }
t|
ƒdkr¾|jdfS |jdfS d	S )
zÖ
    Compute the Galois group of a polynomial of degree 5.

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

    Based on Alg 6.3.9 of [1], but uses resolvent coeff lookup, plus
    factorization over an algebraic extension.

    r   rw   r#   rQ   TF)Údomainr/   N)rI   rx   r0   r3   r   r   r   rE   r   rG   r   ry   rz   r{   r   Zalg_field_from_polyZfactor_listrl   r}   r~   )r9   r:   rK   rx   Ú_Tr;   r>   rd   rc   rf   rt   r   r   r   Ú(_galois_group_degree_5_lookup_ext_factorz  s.    

þ
ÿ

rƒ   c                 C   sŒ  ddl m} tƒ }t|ƒD ]2}t| dƒ}t|tƒr6 qRt| ||| d�\}} qt‚t	|tƒ}t
tƒ}	|d D ]\}
}|	t|
ƒd   |
¡ qlttdd„ |	 ¡ D ƒg ƒƒ}t| ƒ}|dddgkræ|	d d }t|ƒrÜ|jd	fS |jd	fS |ddgk�r,|	d \}}t|ƒ�pt|ƒ}|�r"|jd	fS |jd	fS |dd
gk�rv|�rJ|jdfS |	d
 d }t|ƒ�rj|jd	fS |jd	fS nn|ddd
gk�r |�r–|jdfS |jd	fS |ddgk�rÈ|�r¾|jdfS |jd	fS |ddddgk�rä|jd	fS |dgk�sôt‚tƒ }t|ƒD ]8}t| dƒ}t|tƒ�r" �q@t| ||| d�\}} �qt‚t| ƒ}t|tƒ�rn|�rd|j dfS |j!d	fS |�r~|j"dfS |j#d	fS dS )z£
    Compute the Galois group of a polynomial of degree 6.

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

    Based on Alg 6.3.10 of [1], but uses resolvent coeff lookup.

    r   )ÚS6TransitiveSubgroupsr#   rQ   c                 S   s   g | ]\}}|gt |ƒ ‘qS r   rk   )r+   rB   Úffr   r   r   r.   Ç  s    z1_galois_group_degree_6_lookup.<locals>.<listcomp>r"   r!   Frp   Tr/   ro   N)$rI   r„   r0   r3   r   r   r   rE   r   r   r   Úlistrl   Úappendrq   rr   r|   rG   ZC6ZD6ZG18ZG36mZS4pZA4xC2ZS4xC2rY   ZS4mZPSL2F5ZPGL2F5rJ   rs   r   ZA6ZS6ZG36pZG72)r9   r:   rK   r„   r;   r>   rd   rc   rt   Zfactors_by_degrm   ru   ZT_has_sq_discÚf1Úf2Z
any_squarer   r   r   Ú_galois_group_degree_6_lookup§  sˆ    


þ

ÿþÿÿ
ÿÿÿ

þÿÿrŠ   ©Úby_namer:   rK   c          	   
   O   sh   |pg }|pi }zt | f|ž|Ž\}}W n. tk
rV } ztdd|ƒ‚W 5 d}~X Y nX |j|||d�S )a˜  
    Compute the Galois group for polynomials *f* up to degree 6.

    Examples
    ========

    >>> from sympy import galois_group
    >>> from sympy.abc import x
    >>> f = x**4 + 1
    >>> G, alt = galois_group(f)
    >>> print(G)
    PermutationGroup([
    (0 1)(2 3),
    (0 2)(1 3)])

    The group is returned along with a boolean, indicating whether it is
    contained in the alternating group $A_n$, where $n$ is the degree of *T*.
    Along with other group properties, this can help determine which group it
    is:

    >>> alt
    True
    >>> G.order()
    4

    Alternatively, the group can be returned by name:

    >>> G_name, _ = galois_group(f, by_name=True)
    >>> print(G_name)
    S4TransitiveSubgroups.V

    The group itself can then be obtained by calling the name's
    ``get_perm_group()`` method:

    >>> G_name.get_perm_group()
    PermutationGroup([
    (0 1)(2 3),
    (0 2)(1 3)])

    Group names are values of the enum classes
    :py:class:`sympy.combinatorics.galois.S1TransitiveSubgroups`,
    :py:class:`sympy.combinatorics.galois.S2TransitiveSubgroups`,
    etc.

    Parameters
    ==========

    f : Expr
        Irreducible polynomial over :ref:`ZZ` or :ref:`QQ`, whose Galois group
        is to be determined.
    gens : optional list of symbols
        For converting *f* to Poly, and will be passed on to the
        :py:func:`~.poly_from_expr` function.
    by_name : bool, default False
        If ``True``, the Galois group will be returned by name.
        Otherwise it will be returned as a :py:class:`~.PermutationGroup`.
    max_tries : int, default 30
        Make at most this many attempts in those steps that involve
        generating Tschirnhausen transformations.
    randomize : bool, default False
        If ``True``, then use random coefficients when generating Tschirnhausen
        transformations. Otherwise try transformations in a fixed order. Both
        approaches start with small coefficients and degrees and work upward.
    args : optional
        For converting *f* to Poly, and will be passed on to the
        :py:func:`~.poly_from_expr` function.

    Returns
    =======

    Pair ``(G, alt)``
        The first element ``G`` indicates the Galois group. It is an instance
        of one of the :py:class:`sympy.combinatorics.galois.S1TransitiveSubgroups`
        :py:class:`sympy.combinatorics.galois.S2TransitiveSubgroups`, etc. enum
        classes if *by_name* was ``True``, and a :py:class:`~.PermutationGroup`
        if ``False``.

        The second element is a boolean, saying whether the group is contained
        in the alternating group $A_n$ ($n$ the degree of *T*).

    Raises
    ======

    ValueError
        if *f* is of an unsupported degree.

    MaxTriesException
        if could not complete before exceeding *max_tries* in those steps
        that involve generating Tschirnhausen transformations.

    See Also
    ========

    .Poly.galois_group

    Úgalois_groupr#   Nr‹   )r   r   r   r�   )	ÚfrŒ   r:   rK   ZgensÚargsÚFÚoptÚexcr   r   r   r�     s    bÿr�   )r   r   NT)r   F)r   F)r   F)r   F)r   F)r   F).Ú__doc__Úcollectionsr   r7   Zsympy.core.symbolr   r   Zsympy.ntheory.primetestr   Zsympy.polys.domainsr   Zsympy.polys.densebasicr   Zsympy.polys.densetoolsr	   Zsympy.polys.euclidtoolsr
   Zsympy.polys.factortoolsr   r   Z*sympy.polys.numberfields.galois_resolventsr   r   r   r   Z"sympy.polys.numberfields.utilitiesr   Zsympy.polys.polytoolsr   r   r   r   Zsympy.polys.sqfreetoolsr   Zsympy.utilitiesr   r   rE   rG   rL   rj   rv   r€   rƒ   rŠ   r�   r   r   r   r   Ú<module>   s6     ÿ
k

W
+
Q
-
]