o
    ohM                     @   s  d Z ddlmZmZmZmZmZmZmZm	Z	m
Z
mZ ddlmZmZmZmZmZmZmZmZmZmZmZmZ ddlmZmZmZmZmZmZm Z m!Z!m"Z" ddl#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z) ddl*m+Z+m,Z, ddl-m.Z.m/Z/ dd	 Z0d
d Z1dd Z2dd Z3dd Z4dd Z5dd Z6dd Z7dd Z8dd Z9dd Z:dd Z;d2d!d"Z<d2d#d$Z=d2d%d&Z>d2d'd(Z?d2d)d*Z@d2d+d,ZAd-d. ZBd/d0 ZCd1S )3z8Square-free decomposition algorithms and related tools.     )
dup_negdmp_negdup_subdmp_subdup_muldmp_muldup_quodmp_quodup_mul_grounddmp_mul_ground)	dup_stripdup_LCdmp_ground_LC
dmp_zero_p
dmp_ground
dup_degree
dmp_degreedmp_degree_indmp_degree_list	dmp_raise
dmp_injectdup_convert)	dup_diffdmp_diffdmp_diff_in	dup_shift	dmp_shift	dup_monicdmp_ground_monicdup_primitivedmp_ground_primitive)dup_inner_gcddmp_inner_gcddup_gcddmp_gcddmp_resultantdmp_primitive)gf_sqf_listgf_sqf_part)MultivariatePolynomialErrorDomainErrorc                 C   s&   t dd |D }|t| ksJ dS )z=Sanity check the degrees of a computed factorization in K[x].c                 s   s     | ]\}}|t | V  qd S )N)r   ).0fack r.   k/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/sympy/polys/sqfreetools.py	<genexpr>$   s    z%_dup_check_degrees.<locals>.<genexpr>N)sumr   )fresultdegr.   r.   r/   _dup_check_degrees"   s   r5   c                    sX   dg|d  }|D ]\} t ||} fddt||D }q	t|t | |ks*J dS )z=Sanity check the degrees of a computed factorization in K[X].r      c                    s   g | ]
\}}| |  qS r.   r.   )r+   d1d2r-   r.   r/   
<listcomp>-       z&_dmp_check_degrees.<locals>.<listcomp>N)r   ziptuple)r2   ur3   degsr,   degs_facr.   r9   r/   _dmp_check_degrees(   s
   
rA   c                 C   s"   | sdS t t| t| d|| S )a  
    Return ``True`` if ``f`` is a square-free polynomial in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_sqf_p(x**2 - 2*x + 1)
    False
    >>> R.dup_sqf_p(x**2 - 1)
    True

    Tr6   )r   r#   r   )r2   Kr.   r.   r/   	dup_sqf_p1   s   rC   c                 C   sd   t | |rdS t|d D ]"}t| d|||}t ||rqt| |||}t|||dkr/ dS qdS )a  
    Return ``True`` if ``f`` is a square-free polynomial in ``K[X]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    >>> R.dmp_sqf_p(x**2 + 2*x*y + y**2)
    False
    >>> R.dmp_sqf_p(x**2 + y**2)
    True

    Tr6   r   F)r   ranger   r$   r   )r2   r>   rB   ifpgcdr.   r.   r/   	dmp_sqf_pG   s   

rH   c                 C   s   |j stddt|j dd|j}}	 t| d|dd\}}t||d|j}t||jr/nt	| |j
 ||d } }q|| |fS )ag  
    Find a shift of `f` in `K[x]` that has square-free norm.

    The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`).

    Returns `(s,g,r)`, such that `g(x)=f(x-sa)`, `r(x)=\text{Norm}(g(x))` and
    `r` is a square-free polynomial over `k`.

    Examples
    ========

    We first create the algebraic number field `K=k(a)=\mathbb{Q}(\sqrt{3})`
    and rings `K[x]` and `k[x]`:

    >>> from sympy.polys import ring, QQ
    >>> from sympy import sqrt

    >>> K = QQ.algebraic_field(sqrt(3))
    >>> R, x = ring("x", K)
    >>> _, X = ring("x", QQ)

    We can now find a square free norm for a shift of `f`:

    >>> f = x**2 - 1
    >>> s, g, r = R.dup_sqf_norm(f)

    The choice of shift `s` is arbitrary and the particular values returned for
    `g` and `r` are determined by `s`.

    >>> s == 1
    True
    >>> g == x**2 - 2*sqrt(3)*x + 2
    True
    >>> r == X**4 - 8*X**2 + 4
    True

    The invariants are:

    >>> g == f.shift(-s*K.unit)
    True
    >>> g.norm() == r
    True
    >>> r.is_squarefree
    True

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

    This is part of Trager's algorithm for factorizing polynomials over
    algebraic number fields. In particular this function is algorithm
    ``sqfr_norm`` from [Trager76]_.

    See Also
    ========

    dmp_sqf_norm:
        Analogous function for multivariate polynomials over ``k(a)``.
    dmp_norm:
        Computes the norm of `f` directly without any shift.
    dup_ext_factor:
        Function implementing Trager's algorithm that uses this.
    sympy.polys.polytools.sqf_norm:
        High-level interface for using this function.
    ground domain must be algebraicr   r6   Tfront)is_Algebraicr*   r   modto_listdomr   r%   rC   r   unit)r2   rB   sgh_rr.   r.   r/   dup_sqf_normi   s   A
	rV   c                 #   s    |d }dg| }|| fV  |j  t| |}dd tt|t|d D }|D ]}| }d||<  fdd|D }	t| |	||}
||
fV  q)d}	 |d7 }|g| }  | g| }t| |||}||fV  qL)z9Generate a sequence of candidate shifts for dmp_sqf_norm.r6   r   c                 S   s   g | ]
\}}|d kr|qS )r   r.   )r+   dirE   r.   r.   r/   r:      r;   z(_dmp_sqf_norm_shifts.<locals>.<listcomp>c                    s   g | ]}  | qS r.   r.   )r+   s1iar.   r/   r:      s    )rP   r   sortedr<   rD   copyr   )r2   r>   rB   ns0dvar_indicesrE   s1a1f1jsjajfjr.   rY   r/   _dmp_sqf_norm_shifts   s*   


 

rh   c                 C   s   |st | |\}}}|g||fS |jstdt|j |d d|j}t| ||D ]!\}} t| ||dd\}}t	|||d |j}t
|||jrK nq*|| |fS )a  
    Find a shift of ``f`` in ``K[X]`` that has square-free norm.

    The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`).

    Returns `(s,g,r)`, such that `g(x_1,x_2,\cdots)=f(x_1-s_1 a, x_2 - s_2 a,
    \cdots)`, `r(x)=\text{Norm}(g(x))` and `r` is a square-free polynomial over
    `k`.

    Examples
    ========

    We first create the algebraic number field `K=k(a)=\mathbb{Q}(i)` and rings
    `K[x,y]` and `k[x,y]`:

    >>> from sympy.polys import ring, QQ
    >>> from sympy import I

    >>> K = QQ.algebraic_field(I)
    >>> R, x, y = ring("x,y", K)
    >>> _, X, Y = ring("x,y", QQ)

    We can now find a square free norm for a shift of `f`:

    >>> f = x*y + y**2
    >>> s, g, r = R.dmp_sqf_norm(f)

    The choice of shifts ``s`` is arbitrary and the particular values returned
    for ``g`` and ``r`` are determined by ``s``.

    >>> s
    [0, 1]
    >>> g == x*y - I*x + y**2 - 2*I*y - 1
    True
    >>> r == X**2*Y**2 + X**2 + 2*X*Y**3 + 2*X*Y + Y**4 + 2*Y**2 + 1
    True

    The required invariants are:

    >>> g == f.shift_list([-si*K.unit for si in s])
    True
    >>> g.norm() == r
    True
    >>> r.is_squarefree
    True

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

    This is part of Trager's algorithm for factorizing polynomials over
    algebraic number fields. In particular this function is a multivariate
    generalization of algorithm ``sqfr_norm`` from [Trager76]_.

    See Also
    ========

    dup_sqf_norm:
        Analogous function for univariate polynomials over ``k(a)``.
    dmp_norm:
        Computes the norm of `f` directly without any shift.
    dmp_ext_factor:
        Function implementing Trager's algorithm that uses this.
    sympy.polys.polytools.sqf_norm:
        High-level interface for using this function.
    rI   r6   r   TrJ   )rV   rL   r*   r   rM   rN   rO   rh   r   r%   rH   )r2   r>   rB   rQ   rR   rU   rS   rT   r.   r.   r/   dmp_sqf_norm   s   B
ri   c                 C   sP   |j stdt|j |d d|j}t| ||dd\}}t|||d |jS )aE	  
    Norm of ``f`` in ``K[X]``, often not square-free.

    The domain `K` must be an algebraic number field `k(a)` (see :ref:`QQ(a)`).

    Examples
    ========

    We first define the algebraic number field `K = k(a) = \mathbb{Q}(\sqrt{2})`:

    >>> from sympy import QQ, sqrt
    >>> from sympy.polys.sqfreetools import dmp_norm
    >>> k = QQ
    >>> K = k.algebraic_field(sqrt(2))

    We can now compute the norm of a polynomial `p` in `K[x,y]`:

    >>> p = [[K(1)], [K(1),K.unit]]                  # x + y + sqrt(2)
    >>> N = [[k(1)], [k(2),k(0)], [k(1),k(0),k(-2)]] # x**2 + 2*x*y + y**2 - 2
    >>> dmp_norm(p, 1, K) == N
    True

    In higher level functions that is:

    >>> from sympy import expand, roots, minpoly
    >>> from sympy.abc import x, y
    >>> from math import prod
    >>> a = sqrt(2)
    >>> e = (x + y + a)
    >>> e.as_poly([x, y], extension=a).norm()
    Poly(x**2 + 2*x*y + y**2 - 2, x, y, domain='QQ')

    This is equal to the product of the expressions `x + y + a_i` where the
    `a_i` are the conjugates of `a`:

    >>> pa = minpoly(a)
    >>> pa
    _x**2 - 2
    >>> rs = roots(pa, multiple=True)
    >>> rs
    [sqrt(2), -sqrt(2)]
    >>> n = prod(e.subs(a, r) for r in rs)
    >>> n
    (x + y - sqrt(2))*(x + y + sqrt(2))
    >>> expand(n)
    x**2 + 2*x*y + y**2 - 2

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

    Given an algebraic number field `K = k(a)` any element `b` of `K` can be
    represented as polynomial function `b=g(a)` where `g` is in `k[x]`. If the
    minimal polynomial of `a` over `k` is `p_a` then the roots `a_1`, `a_2`,
    `\cdots` of `p_a(x)` are the conjugates of `a`. The norm of `b` is the
    product `g(a1) \times g(a2) \times \cdots` and is an element of `k`.

    As in [Trager76]_ we extend this norm to multivariate polynomials over `K`.
    If `b(x)` is a polynomial in `k(a)[X]` then we can think of `b` as being
    alternately a function `g_X(a)` where `g_X` is an element of `k[X][y]` i.e.
    a polynomial function with coefficients that are elements of `k[X]`. Then
    the norm of `b` is the product `g_X(a1) \times g_X(a2) \times \cdots` and
    will be an element of `k[X]`.

    See Also
    ========

    dmp_sqf_norm:
        Compute a shift of `f` so that the `\text{Norm}(f)` is square-free.
    sympy.polys.polytools.Poly.norm:
        Higher-level function that calls this.
    rI   r6   r   TrJ   )rL   r*   r   rM   rN   rO   r   r%   )r2   r>   rB   rR   rS   rT   r.   r.   r/   dmp_norm9  s
   Hrj   c                 C   s,   t | ||j} t| |j|j}t ||j|S )z3Compute square-free part of ``f`` in ``GF(p)[x]``. )r   rO   r(   rM   )r2   rB   rR   r.   r.   r/   dup_gf_sqf_part  s   rk   c                 C      t d)z3Compute square-free part of ``f`` in ``GF(p)[X]``. +multivariate polynomials over finite fieldsNotImplementedErrorr2   r>   rB   r.   r.   r/   dmp_gf_sqf_part     rq   c                 C   sp   |j rt| |S | s| S |t| |rt| |} t| t| d||}t| ||}|jr1t	||S t
||d S )a  
    Returns square-free part of a polynomial in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_sqf_part(x**3 - 3*x - 2)
    x**2 - x - 2

    See Also
    ========

    sympy.polys.polytools.Poly.sqf_part
    r6   )is_FiniteFieldrk   is_negativer   r   r#   r   r   is_Fieldr   r   )r2   rB   rG   sqfr.   r.   r/   dup_sqf_part  s   


rw   c              	   C   s   |st | |S |jrt| ||S t| |r| S |t| ||r&t| ||} | }t|d D ]}t|t	| d|||||}q.t
| |||}|jrNt|||S t|||d S )z
    Returns square-free part of a polynomial in ``K[X]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    >>> R.dmp_sqf_part(x**3 + 2*x**2*y + x*y**2)
    x**2 + x*y

    r6   )rw   rs   rq   r   rt   r   r   rD   r$   r   r	   ru   r   r    )r2   r>   rB   rG   rE   rv   r.   r.   r/   dmp_sqf_part  s   

rx   Fc                 C   sr   | }t | ||j} t| |j|j|d\}}t|D ]\}\} }t | |j||f||< qt|| |||j|fS )z<Compute square-free decomposition of ``f`` in ``GF(p)[x]``. all)r   rO   r'   rM   	enumerater5   convert)r2   rB   rz   f_origcoefffactorsrE   r-   r.   r.   r/   dup_gf_sqf_list  s   
r   c                 C   rl   )z<Compute square-free decomposition of ``f`` in ``GF(p)[X]``. rm   rn   )r2   r>   rB   rz   r.   r.   r/   dmp_gf_sqf_list  rr   r   c                 C   s  |j r
t| ||dS | }|jrt| |}t| |} nt| |\}} |t| |r1t| |} | }t| dkr;|g fS g d}}t	| d|}t
| ||\}}	}
	 t	|	d|}t|
||}|sf||	|f nt
|	||\}}	}
|swt|dkr~|||f |d7 }qPt|| ||fS )a  
    Return square-free decomposition of a polynomial in ``K[x]``.

    Uses Yun's algorithm from [Yun76]_.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> f = 2*x**5 + 16*x**4 + 50*x**3 + 76*x**2 + 56*x + 16

    >>> R.dup_sqf_list(f)
    (2, [(x + 1, 2), (x + 2, 3)])
    >>> R.dup_sqf_list(f, all=True)
    (2, [(1, 1), (x + 1, 2), (x + 2, 3)])

    See Also
    ========

    dmp_sqf_list:
        Corresponding function for multivariate polynomials.
    sympy.polys.polytools.sqf_list:
        High-level function for square-free factorization of expressions.
    sympy.polys.polytools.Poly.sqf_list:
        Analogous method on :class:`~.Poly`.

    References
    ==========

    [Yun76]_
    ry   r   r6   )rs   r   ru   r   r   r   rt   r   r   r   r!   r   appendr5   )r2   rB   rz   r}   r~   r3   rE   rS   rR   pqr_   r.   r.   r/   dup_sqf_list  s8   "



r   c                 C   sh   t | ||d\}}|r(|d d dkr(t|d d ||}|dfg|dd  S t|g}|dfg| S )a  
    Return square-free decomposition of a polynomial in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> f = 2*x**5 + 16*x**4 + 50*x**3 + 76*x**2 + 56*x + 16

    >>> R.dup_sqf_list_include(f)
    [(2, 1), (x + 1, 2), (x + 2, 3)]
    >>> R.dup_sqf_list_include(f, all=True)
    [(2, 1), (x + 1, 2), (x + 2, 3)]

    ry   r   r6   N)r   r
   r   )r2   rB   rz   r~   r   rR   r.   r.   r/   dup_sqf_list_includeA  s   
r   c                    s  |s	t | ||dS |jrt| |||dS | }|jr&t| ||}t| ||} nt| ||\}} |t| ||r@t| ||} | }t	| |}|dk rM|g fS t
| ||\}} i  |dkrt| d||}t| |||\}	}
}d}	 t|
d||}t||||}t||r|
 |< nt|
|||\}	}
}|st	|	|dkr|	 |< |d7 }qot||d ||d\}}||9 }|D ]\}}|g}| v rt | ||| |< q| |< q fddt D  t||  | fS )a1  
    Return square-free decomposition of a polynomial in `K[X]`.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    >>> f = x**5 + 2*x**4*y + x**3*y**2

    >>> R.dmp_sqf_list(f)
    (1, [(x + y, 2), (x, 3)])
    >>> R.dmp_sqf_list(f, all=True)
    (1, [(1, 1), (x + y, 2), (x, 3)])

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

    Uses Yun's algorithm for univariate polynomials from [Yun76]_ recrusively.
    The multivariate polynomial is treated as a univariate polynomial in its
    leading variable. Then Yun's algorithm computes the square-free
    factorization of the primitive and the content is factored recursively.

    It would be better to use a dedicated algorithm for multivariate
    polynomials instead.

    See Also
    ========

    dup_sqf_list:
        Corresponding function for univariate polynomials.
    sympy.polys.polytools.sqf_list:
        High-level function for square-free factorization of expressions.
    sympy.polys.polytools.Poly.sqf_list:
        Analogous method on :class:`~.Poly`.
    ry   r   r6   Tc                    s   g | ]} | |fqS r.   r.   )r+   rE   r3   r.   r/   r:     s    z dmp_sqf_list.<locals>.<listcomp>)r   rs   r   ru   r   r   r    rt   r   r   r&   r   r"   r   r   dmp_sqf_listr   r[   rA   )r2   r>   rB   rz   r}   r~   r4   contentrS   rR   r   r   rE   r_   coeff_contentresult_contentr,   r.   r   r/   r   ]  sT   &


r   c                 C   s~   |s	t | ||dS t| |||d\}}|r3|d d dkr3t|d d |||}|dfg|dd  S t||}|dfg| S )ah  
    Return square-free decomposition of a polynomial in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    >>> f = x**5 + 2*x**4*y + x**3*y**2

    >>> R.dmp_sqf_list_include(f)
    [(1, 1), (x + y, 2), (x, 3)]
    >>> R.dmp_sqf_list_include(f, all=True)
    [(1, 1), (x + y, 2), (x, 3)]

    ry   r   r6   N)r   r   r   r   )r2   r>   rB   rz   r~   r   rR   r.   r.   r/   dmp_sqf_list_include  s   
r   c                 C   s   | st dt| |} t| sg S t| t| |j||}t||}t|D ]\}\}}t|t||| ||}||d f||< q%t	| ||} t| sM|S | dfg| S )z
    Compute greatest factorial factorization of ``f`` in ``K[x]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x = ring("x", ZZ)

    >>> R.dup_gff_list(x**5 + 2*x**4 - x**3 - 2*x**2)
    [(x, 1), (x + 2, 4)]

    zDgreatest factorial factorization doesn't exist for a zero polynomialr6   )

ValueErrorr   r   r#   r   onedup_gff_listr{   r   r   )r2   rB   rR   HrE   rS   r-   r.   r.   r/   r     s   

r   c                 C   s   |st | |S t| )z
    Compute greatest factorial factorization of ``f`` in ``K[X]``.

    Examples
    ========

    >>> from sympy.polys import ring, ZZ
    >>> R, x,y = ring("x,y", ZZ)

    )r   r)   rp   r.   r.   r/   dmp_gff_list  s   
r   N)F)D__doc__sympy.polys.densearithr   r   r   r   r   r   r   r	   r
   r   sympy.polys.densebasicr   r   r   r   r   r   r   r   r   r   r   r   sympy.polys.densetoolsr   r   r   r   r   r   r   r   r    sympy.polys.euclidtoolsr!   r"   r#   r$   r%   r&   sympy.polys.galoistoolsr'   r(   sympy.polys.polyerrorsr)   r*   r5   rA   rC   rH   rV   rh   ri   rj   rk   rq   rw   rx   r   r   r   r   r   r   r   r   r.   r.   r.   r/   <module>   s6    08, 	"R(VQ$
%


M

l%