
    sgP                     >   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e      Z$	 	 ddZ%d Z&ddZ'ddZ(ddZ)ddZ*ddZ+ddZ,e#ddddd       Z-y) z
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                       e Zd Zy)MaxTriesExceptionN)__name__
__module____qualname__     X/var/www/html/venv/lib/python3.12/site-packages/sympy/polys/numberfields/galoisgroups.pyr   r   #   s    r   r      c                 8   t        d      }| j                         }|
t               }|j                  | j                         |ri d}d}fd}	t        |      D ]1  }
|r| |	      }t        |      }t        d |D              }||z   kD  r(|dk(  r|dz  }|dz
  }n|dz  } |	|      }t        |      }t        d      g|D cg c]  }t        |       c}z   }n>t        |
dz  dz   |      }t        j                  d|dz
        }t        || |t              }t        || j                        }t        | j                  ||z
        |      }|j                  |vst!        |j                  j#                         t              s.||fc S  t$        c c}w )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*.

    X      c                 J    j                  | t        | d            }|| <   |S )N   )getr   )degreegencoeff_generatorss     r   get_coeff_generatorz9tschirnhausen_transformation.<locals>.get_coeff_generatorc   s,    ""6<+BC#& 
r   c              3   2   K   | ]  }t        |        y w)N)abs).0cs     r   	<genexpr>z/tschirnhausen_transformation.<locals>.<genexpr>x   s     +qCF+s   r&      )r   r(   setaddreprangenextmaxr   minrandomrandintr   r   r)   	resultantr   to_listr   )T	max_coeff	max_trieshistoryfixed_orderr"   ndeg_coeff_sumcurrent_degreer+   ir)   coeffsmr/   aCdAUr*   s                       @r   tschirnhausen_transformationrM   '   s   b 	c
A	
A%KK
 9 &  &n5C#YF+F++A!M1!Q&!Q&M%2Q%6N"a'N).9cA&1Q2a511A AqD1Hi(Aq!a%(A1qb!R(AAEENQU#Q'55Iaeemmor$Ba4KM&N  2s   Fc                 x    t        | t              r| j                         nt        | t              }t        |      S )z?Convenience to check if a Poly or dup has square discriminant. )
isinstancer   discriminantr
   r   r   )r=   rJ   s     r   has_square_discrQ      s+    &q$/5Ea5LAQ<r   Fc                 \    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.galoisrS   rQ   A3S3)r=   r?   	randomizerS   s       r   _galois_group_degree_3rX      s6     A0?0B"%%t, 4'**E24r   c           	         ddl m} ddlm} t	        d      }|d   |d   z  |d   |d   z  z   } |d        |d      dd        |d      dd      g}t        |||      }|d   |d   dz  z  |d   |d   dz  z  z   |d   |d   dz  z  z   |d   |d   dz  z  z   }	 |d        |d      dd      g}
t               }t        |      D ]"  }|dkD  rt        | |||       \  }} |j                  | d	
      \  }}}t        |t              sDt        |       }|"|r|j                  d	fc S |j                  dfc S |r|j                  d	fc S ||   }|	j!                  t#        | ||            d	      }|
D cg c]
  }||z  |z   }}t        |||      }|j                  |       \  }}}t%        |t              }|dk(  rt'        |      r|j(                  dfc S |j*                  dfc S  t,        c c}w )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@   rA   T)find_integer_rootFsimultaneous) sympy.combinatorics.permutationsr[   rT   r]   r   r   r2   r5   rM   eval_for_polyr   r   rQ   A4S4Vsubszipr
   r   C4D4r   )r=   r?   rW   r[   r]   r"   F1s1R1F2_pres2_prer@   rE   _R_dupi0sq_discsigmaF2taus2R2rJ   s                          r   "_galois_group_degree_4_root_approxry      s]    =@A
 
1adQqT!A$Y	BAAq!Aq!
B
 
2q"	B
 qT!A$'\AaD1qL(1Q4!a<7!A$qtQw,FFAAq!F
 eG9 .5q5/Y8?@IMKDAq ''T'Bq"# "!$: 9@*--t4 </22E:< )++T22 2 [[Qa)[=)/0#eCio00r1b!&&q)q!UB'6Q<),,e44),,e44].5`  1s   9G4c                 .   ddl m} t               }t        |      D ]3  }t	        | d      }t        |t              r nt        | |||       \  }} 5 t        t        |t              }t        t        |d   D 	
cg c]  \  }	}
t        |	      dz
  g|
z   c}
}	g             }|dgk(  r't        |       r|j                  dfS |j                  dfS |g dk(  r|j                   dfS |g d	k(  r|j"                  dfS |d
dgk(  sJ |j$                  dfS c c}
}	w )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   r\   r^   r&      TFr&   r&      )r$   r$   r$   r$   r}   )rT   r]   r2   r5   r   r   r   rM   r   r   sortedsumlenrQ   rd   re   ri   rf   rj   )r=   r?   rW   r]   r@   rE   rq   rp   flreLs               r   _galois_group_degree_4_lookupr      s<    AeG9  '1-UB+A4;<EG1	    
	#Bs%'U!QQ!q	 	A 	QCx4CA4F&))40 	4'**E2	4 	I~%((%00I~%''..A;;!$$e,,s   :Dc           	      ~   ddl m} ddlm} t	        d      }t               }|d   \  }}}	 |j                  | }t        |||	      }
t               }d}t        |      D ]  }|dkD  rt        | |||       \  }} t        | d      }t        |t              s9|sOt        |       }t        |t              r"|r|j                   d	fc S |j"                  dfc S |s|j$                  dfc S d	}|
j'                  |       }|j)                         D ]  \  }}t+        ||t              r n |}|d   |d   d
z  z  |d   |d
   d
z  z  z   |d
   |d   d
z  z  z   |d   |d   d
z  z  z   |d   |d   d
z  z  z   } |d         |d      dd      d
d      g}}|	|   }|j-                  t/        | ||            d	      }|D cg c]
  }||z  |z   }}t        |||      }|j1                  |       \  }}}t3        |t              }|dk(  rt5        |      r|j6                  d	fc S |j8                  d	fc S  t:        c c}w )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   S5TransitiveSubgroupsrZ   zX0,X1,X2,X3,X4)r1   r&   Fr^   r&   Tr$   r#   r}   r`   )rT   r   rb   r[   r   r   as_exprr   r2   r5   rM   r   r   r   rQ   r   A5S5M20 round_roots_to_integers_for_polyitemsr	   rg   rh   rc   r
   r   C5D5r   )r=   r?   rW   r   r[   X5resF51rp   s51R51r@   reached_second_stagerE   R51_duprs   rounded_rootspermutation_indexcandidate_rootr"   rn   ro   rr   rt   ru   rv   rw   rx   rq   rJ   s                                 r   _galois_group_degree_5_hybridr   )  s    A<	!	"B

Cf+KCC
#++r
C
CS
!CeG 9 64q5/Y8?@IMKDAq *!Q/"%
 $%a(G "-<C.1148 @366>@ -11599  $ <<Q? 2?1D1D1F 	-~G^R8	 1adAg!QqT1W,qtAaD!G|;ad1Q47lJQqTRSTURVXYRY\YN NKN1a A&

 B[[Qa)[=)/0#eCio00r1b!&&q)q!UB'6Q<),,d33),,d33m64p  1s   >H:c                    ddl m} | }t               }t        |      D ]3  }t	        | d      }t        |t              r nt        | |||       \  }} 5 t        t        |       }	t        |t              r|	r|j                  dfS |j                  dfS |	s|j                  dfS t        |t        j                  |            j!                         d   }
t#        |
      dk(  r|j$                  dfS |j&                  df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&   r^   TF)domainr1   )rT   r   r2   r5   r   r   r   rM   r   rQ   r   r   r   r   r   alg_field_from_polyfactor_listr   r   r   )r=   r?   rW   r   _Tr@   rE   rq   rp   rs   r   s              r   (_galois_group_degree_5_lookup_ext_factorr   z  s    A	
BeG9  '1-UB+A4;<EG1	   a G#4;&))40 	8+..6	8 %))511
 
b//3	4	@	@	B1	EB
2w!|%(($//%(($//r   c                    ddl m} t               }t        |      D ]3  }t	        | d      }t        |t              r nt        | |||       \  }} 5 t        t        |t              }t        t              }	|d   D ]%  \  }
}|	t        |
      dz
     j                  |
       ' t        t        |	j!                         D cg c]  \  }}|gt        |      z   c}}g             }t#        |       }|g dk(  r/|	d   d   }t#        |      r|j$                  dfS |j&                  dfS |ddgk(  r>|	d   \  }}t#        |      xs t#        |      }|r|j(                  dfS |j*                  dfS |dd	gk(  r?|r|j,                  d
fS |	d	   d   }t#        |      r|j.                  dfS |j0                  dfS |g dk(  r|r|j2                  d
fS |j4                  dfS |ddgk(  r|r|j6                  d
fS |j8                  dfS |g dk(  r|j:                  dfS |dgk(  sJ t               }t        |      D ]3  }t	        | d      }t        |t              r nt        | |||       \  }} 5 t        t#        |       }t=        |t              r|r|j>                  d
fS |j@                  dfS |r|jB                  d
fS |jD                  dfS c c}}w )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&   r^   )r&   r$   r#   r#   Fr$   r}   Tr|   r1   )r&   r&   r&   r#   r{   )#rT   r   r2   r5   r   r   r   rM   r   r   r   listr   appendr~   r   r   rQ   C6D6G18G36mS4pA4xC2S4xC2rd   S4mPSL2F5PGL2F5rV   r   A6S6G36pG72)r=   r?   rW   r   r@   rE   rq   rp   r   factors_by_degr   rJ   ffr   T_has_sq_discf1f2
any_squares                     r   _galois_group_degree_6_lookupr     sI    A eG9  '1-UB+A4;<EG1	   		#B !&N1 -1s1vz"))!,- 	s#1#7#7#9!Rc"g	 	A $A&MI~Aq!5DR5H&))51 	8+..6	8 
q!f"B$R(?OB,?
6@&**E2 	:+00%8	: 
q!f)--t44"1%B<KB<O*00%8 ?/55u=? 
i4A&))40 	9+//7	9 
q!f8E&--t4 	<+22E:	< 
l	%((%008O8 eG9  '1-UB+A4;<EG1	   #A&M#4A&))40 	8+..6	8 7D&++T2 	9+//7	9ss   Kby_namer?   rW   c                    |xs g }|xs i }	 t        | g|i |\  }}|j                  |||      S # t        $ r}t        dd|      d}~ww xY w)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?   rW   gensargsFoptexcs	            r   r   r     st    D :2D:2D81D1D13 >>'Y$-  / /  83778s   4 	AA

A)
   r    NT)r    F).__doc__collectionsr   r9   sympy.core.symbolr   r   sympy.ntheory.primetestr   sympy.polys.domainsr   sympy.polys.densebasicr   sympy.polys.densetoolsr	   sympy.polys.euclidtoolsr
   sympy.polys.factortoolsr   r   *sympy.polys.numberfields.galois_resolventsr   r   r   r   "sympy.polys.numberfields.utilitiesr   sympy.polys.polytoolsr   r   r   r   sympy.polys.sqfreetoolsr   sympy.utilitiesr   r   rM   rQ   rX   ry   r   r   r   r   r   r   r   r   <module>r      s    $  , - " - + 4 F  <J J - ",  IM-1hV4Tn(-VNb*0ZZ9z #(B% j/ j/r   