U
    ;qLeP                     @   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   |/home/p21-0144/sympy/latex2sympy2solve-back-end/sympyEq/lib/python3.8/site-packages/sympy/polys/numberfields/galoisgroups.pyr   #   s   r   
      Tc                    sP  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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&   	resultantr   r   )TZ	max_coeff	max_trieshistoryfixed_orderr    nZdeg_coeff_sumZcurrent_degreer(   ir&   coeffsmaCdAUr   r'   r   tschirnhausen_transformation'   s>    1
rG   c                 C   s$   t | tr|  nt| t}t|S )z?Convenience to check if a Poly or dup has square discriminant. )
isinstancer   discriminantr
   r   r   )r:   rD   r   r   r   has_square_disc   s    rJ   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.galoisrK   rJ   A3S3)r:   r;   	randomizerK   r   r   r   _galois_group_degree_3   s    
rP   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*qt| }|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rqt|r|jdf  S |jdf  S qt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simultaneousc                    s   g | ]} |   qS r   r   r+   tausigmar   r   r.      s     z6_galois_group_degree_4_root_approx.<locals>.<listcomp>) sympy.combinatorics.permutationsrR   rL   rT   r   r   r0   r3   rG   eval_for_polyr   r   rJ   A4S4Vsubszipr
   r   C4D4r   )r:   r;   rO   rR   rT   r    F1s1R1F2_pres2_prer<   r?   _R_dupi0sq_discF2s2R2rD   r   rZ   r   "_galois_group_degree_4_root_approx   sT    
 P





rq   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rt| 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st|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   rS   rU   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"   )rL   rT   r0   r3   r   r   r   rG   r   r   sortedsumrJ   r^   r_   rc   r`   AssertionErrorrd   )
r:   r;   rO   rT   r<   r?   rk   rj   flLr   r   r   _galois_group_degree_4_lookup   s6    







r}   c                    s(  ddl m} ddlm} td}t }|d \}}}	|j| }t|||	}
t }d}t	|D ]}|dkrt
| ||| d\}} t| d}t|tsq\|st| }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rq\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   S5TransitiveSubgroupsrQ   zX0,X1,X2,X3,X4)r/   r#   FrU   r#   Tr"   r!   rw   rV   c                    s   g | ]} |   qS r   r   rX   rZ   r   r   r.   k  s     z1_galois_group_degree_5_hybrid.<locals>.<listcomp>N)rL   r   r\   rR   r   r   as_exprr   r0   r3   rG   r   r   r   rJ   r   A5S5M20Z round_roots_to_integers_for_polyitemsr	   ra   rb   r]   r
   r   C5D5r   )r:   r;   rO   r   rR   ZX5resZF51rj   Zs51ZR51r<   Zreached_second_stager?   ZR51_duprm   Zrounded_rootsZpermutation_indexZcandidate_rootr    rh   ri   rl   rn   ro   rp   rk   rD   r   rZ   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   r~   r#   rU   TF)domainr/   N)rL   r   r0   r3   r   r   r   rG   r   rJ   r   r   r   r   r   alg_field_from_polyfactor_listrs   r   r   )r:   r;   rO   r   Z_Tr<   r?   rk   rj   rm   r{   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st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#   rU   c                 S   s   g | ]\}}|gt | qS r   rr   )r+   rD   ffr   r   r   r.     s    z1_galois_group_degree_6_lookup.<locals>.<listcomp>r"   r!   Frw   Tr/   rv   N)$rL   r   r0   r3   r   r   r   rG   r   r   r   listrs   appendrx   ry   r   rJ   ZC6ZD6ZG18ZG36mZS4pZA4xC2ZS4xC2r^   ZS4mZPSL2F5ZPGL2F5rN   rz   r   ZA6ZS6ZG36pZG72)r:   r;   rO   r   r<   r?   rk   rj   r{   Zfactors_by_degrt   r|   ZT_has_sq_discf1f2Z
any_squarer   r   r   _galois_group_degree_6_lookup  s    







r   by_namer;   rO   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;   rO   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   sympy.core.symbolr   r   sympy.ntheory.primetestr   sympy.polys.domainsr   sympy.polys.densebasicr   sympy.polys.densetoolsr	   sympy.polys.euclidtoolsr
   sympy.polys.factortoolsr   r   Z*sympy.polys.numberfields.galois_resolventsr   r   r   r   Z"sympy.polys.numberfields.utilitiesr   sympy.polys.polytoolsr   r   r   r   sympy.polys.sqfreetoolsr   Zsympy.utilitiesr   r   rG   rJ   rP   rq   r}   r   r   r   r   r   r   r   r   <module>   s6     
k

W
+
Q
-
]