o
    8VaC:                     @   s   d Z ddlmZmZmZmZ ddlmZmZmZm	Z	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 ddlmZ dd	lmZ G d
d dZG dd dZdS )a  
This module contains functions for two multivariate resultants. These
are:

- Dixon's resultant.
- Macaulay's resultant.

Multivariate resultants are used to identify whether a multivariate
system has common roots. That is when the resultant is equal to zero.
    )IndexedBaseMatrixMulPoly)remproddegree_listdiagsimplify)itermonomialsmonomial_deg)monomial_key)poly_from_exprtotal_degree)binomial)combinations_with_replacement)SymPyDeprecationWarningc                   @   sd   e Zd ZdZdd Zedd Zdd Zdd	 Zd
d Z	dd Z
dd Zdd Zdd Zdd ZdS )DixonResultantaL  
    A class for retrieving the Dixon's resultant of a multivariate
    system.

    Examples
    ========

    >>> from sympy.core import symbols

    >>> from sympy.polys.multivariate_resultants import DixonResultant
    >>> x, y = symbols('x, y')

    >>> p = x + y
    >>> q = x ** 2 + y ** 3
    >>> h = x ** 2 + y

    >>> dixon = DixonResultant(variables=[x, y], polynomials=[p, q, h])
    >>> poly = dixon.get_dixon_polynomial()
    >>> matrix = dixon.get_dixon_matrix(polynomial=poly)
    >>> matrix
    Matrix([
    [ 0,  0, -1,  0, -1],
    [ 0, -1,  0, -1,  0],
    [-1,  0,  1,  0,  0],
    [ 0, -1,  0,  0,  1],
    [-1,  0,  0,  1,  0]])
    >>> matrix.det()
    0

    See Also
    ========

    Notebook in examples: sympy/example/notebooks.

    References
    ==========

    .. [1] [Kapur1994]_
    .. [2] [Palancz08]_

    c                    sd   |_ |_tj_tj _td  fddtjD _fddtjD _dS )aV  
        A class that takes two lists, a list of polynomials and list of
        variables. Returns the Dixon matrix of the multivariate system.

        Parameters
        ----------
        polynomials : list of polynomials
            A  list of m n-degree polynomials
        variables: list
            A list of all n variables
        Zalphac                    s   g | ]} | qS  r   .0i)ar   E/usr/lib/python3/dist-packages/sympy/polys/multivariate_resultants.py
<listcomp>T       z+DixonResultant.__init__.<locals>.<listcomp>c                    s$   g | ] t  fd djD qS )c                 3   s    | ]	}t |  V  qd S N)r   r   polyr   r   r   	<genexpr>W   s    z5DixonResultant.__init__.<locals>.<listcomp>.<genexpr>)maxpolynomialsr   selfr   r   r   W       N)	r"   	variableslennmr   rangedummy_variables_max_degreesr%   r"   r'   r   )r   r%   r   __init__@   s   
zDixonResultant.__init__c                 C   s   t dddd  | jS )Nmax_degreescE  1.5)featureissuedeprecated_since_version)r   warnr-   r$   r   r   r   r0   Z   s   zDixonResultant.max_degreesc                    s   | j | jd krtd| jg}t| j}t| jD ]!}| j| ||< dd t| j|D  |	 fdd| jD  qt
|}t| j| j}tdd |D  }| |  }t|| jd S )	a  
        Returns
        =======

        dixon_polynomial: polynomial
            Dixon's polynomial is calculated as:

            delta = Delta(A) / ((x_1 - a_1) ... (x_n - a_n)) where,

            A =  |p_1(x_1,... x_n), ..., p_n(x_1,... x_n)|
                 |p_1(a_1,... x_n), ..., p_n(a_1,... x_n)|
                 |...             , ...,              ...|
                 |p_1(a_1,... a_n), ..., p_n(a_1,... a_n)|
           z%Method invalid for given combination.c                 S   s   i | ]\}}||qS r   r   )r   vartr   r   r   
<dictcomp>z       z7DixonResultant.get_dixon_polynomial.<locals>.<dictcomp>c                    s   g | ]}|  qS r   )Zsubs)r   fZsubstitutionr   r   r   {   r;   z7DixonResultant.get_dixon_polynomial.<locals>.<listcomp>c                 S   s   g | ]\}}|| qS r   r   )r   r   br   r   r   r      s    r   )r*   r)   
ValueErrorr"   listr'   r+   r,   zipappendr   r   ZdetZfactorr   )r%   rowstempidxAZtermsZproduct_of_differencesZdixon_polynomialr   r=   r   get_dixon_polynomiala   s   
z#DixonResultant.get_dixon_polynomialc                    sH   t ddddd   fddt jD }t|}t| }t| S )Nget_upper_degreeget_max_degreesr1   r2   )r3   Z
useinsteadr4   r5   c                    s    g | ]} j |  j|  qS r   )r'   r-   r   r$   r   r   r          z3DixonResultant.get_upper_degree.<locals>.<listcomp>)r   r6   r+   r)   r   r   Zmonomsr   )r%   Zlist_of_productsproductr   r$   r   rH      s   
zDixonResultant.get_upper_degreec                    s,    fdd|  D }dd t| D }|S )z
        Returns a list of the maximum degree of each variable appearing
        in the coefficients of the Dixon polynomial. The coefficients are
        viewed as polys in x_1, ... , x_n.
        c                    s   g | ]
}t t| jqS r   )r   r   r'   r   r$   r   r   r      s    z2DixonResultant.get_max_degrees.<locals>.<listcomp>c                 S   s   g | ]}t |qS r   )r!   )r   Zdegsr   r   r   r      r   )coeffsrA   )r%   
polynomialZ	deg_listsr0   r   r$   r   rI      s
   
zDixonResultant.get_max_degreesc                    s    |}tj|tdtdjdtfdd| D   jd  jd krD fddt jd	 D } d
d
|f   S )z
        Construct the Dixon matrix from the coefficients of polynomial
        \alpha. Each coefficient is viewed as a polynomial of x_1, ...,
        x_n.
        Tlexreversekeyc                    s    g | ]  fd dD qS )c                    s$   g | ]}t  gjR  |qS r   )r   r'   coeff_monomial)r   r*   )cr%   r   r   r      r&   >DixonResultant.get_dixon_matrix.<locals>.<listcomp>.<listcomp>r   r#   )	monomialsr%   )rS   r   r      s
    
z3DixonResultant.get_dixon_matrix.<locals>.<listcomp>r   r7   c                    s.   g | ]}t d d  dd|f D r|qS )c                 S   s   g | ]}|d kqS )r   r   )r   elementr   r   r   r      r   rT   N)any)r   column)dixon_matrixr   r   r      s
    
N)	rI   r   r'   sortedr   r   rL   shaper+   )r%   rM   r0   keepr   )rY   rU   r%   r   get_dixon_matrix   s   

zDixonResultant.get_dixon_matrixc                    s    j rdS  j\}t  d   fddt|D } |ddf  tdgd  dg g} dddf |kr?dS dS )	a  
        Test for the validity of the Kapur-Saxena-Yang precondition.

        The precondition requires that the column corresponding to the
        monomial 1 = x_1 ^ 0 * x_2 ^ 0 * ... * x_n ^ 0 is not a linear
        combination of the remaining ones. In sympy notation this is
        the last column. For the precondition to hold the last non-zero
        row of the rref matrix should be of the form [0, 0, ..., 1].
        Fr   c                    s,   g | ] t  fd dtD r qS )c                 3   s     | ]} |f d kV  qdS )r   Nr   r   j)r   matrixr   r   r       s    z=DixonResultant.KSY_precondition.<locals>.<listcomp>.<genexpr>)rW   r+   r#   ra   r)   r   r   r      s   , z3DixonResultant.KSY_precondition.<locals>.<listcomp>Nr7   rZ   T)is_zero_matrixr\   r
   Zrrefr+   r   )r%   ra   r*   rC   Z	conditionr   rb   r   KSY_precondition   s   

zDixonResultant.KSY_preconditionc                    s<    fddt  jD } fddt  jD } ||f S )z/Remove the zero rows and columns of the matrix.c                       g | ]
}  |js|qS r   )rowrc   r   ra   r   r   r      
    z?DixonResultant.delete_zero_rows_and_columns.<locals>.<listcomp>c                    re   r   )colrc   r_   rg   r   r   r      rh   )r+   rC   cols)r%   ra   rC   rj   r   rg   r   delete_zero_rows_and_columns   s   

z+DixonResultant.delete_zero_rows_and_columnsc                 C   s<   d}t |jD ]}||D ]}|dkr|| } nqq|S )z;Calculate the product of the leading entries of the matrix.r7   r   )r+   rC   rf   )r%   ra   resrf   elr   r   r   product_leading_entries   s   z&DixonResultant.product_leading_entriesc                 C   s0   |  |}| \}}}|  t|}| |S )z@Calculate the Kapur-Saxena-Yang approach to the Dixon Resultant.)rk   ZLUdecompositionr
   rn   )r%   ra   _Ur   r   r   get_KSY_Dixon_resultant   s   

z&DixonResultant.get_KSY_Dixon_resultantN)__name__
__module____qualname____doc__r/   propertyr0   rG   rH   rI   r^   rd   rk   rn   rq   r   r   r   r   r      s    *
$	
r   c                   @   sP   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd ZdS )MacaulayResultanta2  
    A class for calculating the Macaulay resultant. Note that the
    polynomials must be homogenized and their coefficients must be
    given as symbols.

    Examples
    ========

    >>> from sympy.core import symbols

    >>> from sympy.polys.multivariate_resultants import MacaulayResultant
    >>> x, y, z = symbols('x, y, z')

    >>> a_0, a_1, a_2 = symbols('a_0, a_1, a_2')
    >>> b_0, b_1, b_2 = symbols('b_0, b_1, b_2')
    >>> c_0, c_1, c_2,c_3, c_4 = symbols('c_0, c_1, c_2, c_3, c_4')

    >>> f = a_0 * y -  a_1 * x + a_2 * z
    >>> g = b_1 * x ** 2 + b_0 * y ** 2 - b_2 * z ** 2
    >>> h = c_0 * y * z ** 2 - c_1 * x ** 3 + c_2 * x ** 2 * z - c_3 * x * z ** 2 + c_4 * z ** 3

    >>> mac = MacaulayResultant(polynomials=[f, g, h], variables=[x, y, z])
    >>> mac.monomial_set
    [x**4, x**3*y, x**3*z, x**2*y**2, x**2*y*z, x**2*z**2, x*y**3,
    x*y**2*z, x*y*z**2, x*z**3, y**4, y**3*z, y**2*z**2, y*z**3, z**4]
    >>> matrix = mac.get_matrix()
    >>> submatrix = mac.get_submatrix(matrix)
    >>> submatrix
    Matrix([
    [-a_1,  a_0,  a_2,    0],
    [   0, -a_1,    0,    0],
    [   0,    0, -a_1,    0],
    [   0,    0,    0, -a_1]])

    See Also
    ========

    Notebook in examples: sympy/example/notebooks.

    References
    ==========

    .. [1] [Bruce97]_
    .. [2] [Stiller96]_

    c                    sR   | _ | _t| _ fdd j D  _   _   _ 	 j _
dS )z
        Parameters
        ==========

        variables: list
            A list of all n variables
        polynomials : list of sympy polynomials
            A  list of m n-degree polynomials
        c                    s   g | ]}t |g jR  qS r   )r   r'   r   r$   r   r   r   /      z.MacaulayResultant.__init__.<locals>.<listcomp>N)r"   r'   r(   r)   degrees_get_degree_mdegree_mget_sizeZmonomials_sizeget_monomials_of_certain_degreemonomial_setr.   r   r$   r   r/      s   




zMacaulayResultant.__init__c                 C   s   dt dd | jD  S )z
        Returns
        =======

        degree_m: int
            The degree_m is calculated as  1 + \sum_1 ^ n (d_i - 1),
            where d_i is the degree of the i polynomial
        r7   c                 s   s    | ]}|d  V  qdS )r7   Nr   )r   dr   r   r   r    A  s    z2MacaulayResultant._get_degree_m.<locals>.<genexpr>)sumry   r$   r   r   r   rz   8  s   	zMacaulayResultant._get_degree_mc                 C   s   t | j| j d | jd S )z
        Returns
        =======

        size: int
            The size of set T. Set T is the set of all possible
            monomials of the n variables for degree equal to the
            degree_m
        r7   )r   r{   r)   r$   r   r   r   r|   C  s   
zMacaulayResultant.get_sizec                 C   s,   dd t | j|D }t|dtd| jdS )zw
        Returns
        =======

        monomials: list
            A list of monomials of a certain degree.
        c                 S   s   g | ]}t | qS r   )r   )r   monomialr   r   r   r   W  r   zEMacaulayResultant.get_monomials_of_certain_degree.<locals>.<listcomp>TrN   rO   )r   r'   r[   r   )r%   degreerU   r   r   r   r}   O  s   
z1MacaulayResultant.get_monomials_of_certain_degreec                    s   g }g }t | jD ]V}|dkr"| j| j|  }| |}|| q	|| j|d  | j|d    | j| j|  }| |}|D ]}|D ] t |dkrX fdd|D }qFqB|| q	|S )z
        Returns
        =======

        row_coefficients: list
            The row coefficients of Macaulay's matrix
        r   r7   c                    s   g | ]}| kr|qS r   r   )r   itempr   r   r   u  s    
z:MacaulayResultant.get_row_coefficients.<locals>.<listcomp>)r+   r)   r{   ry   r}   rB   r'   r   )r%   row_coefficients	divisibler   r   r   Z	poss_rowsZdivr   r   r   get_row_coefficients^  s(   

z&MacaulayResultant.get_row_coefficientsc           	      C   s|   g }|   }t| jD ],}|| D ]%}g }t| j| | g| jR  }| jD ]
}||| q&|| qqt	|}|S )zt
        Returns
        =======

        macaulay_matrix: Matrix
            The Macaulay numerator matrix
        )
r   r+   r)   r   r"   r'   r~   rB   rR   r   )	r%   rC   r   r   Z
multiplierZcoefficientsr   ZmonoZmacaulay_matrixr   r   r   
get_matrixz  s   
	zMacaulayResultant.get_matrixc                    s   g } j D ]"}g }t jD ]\}}|tt|| j| k q|| q fddt|D } fddt|D }||fS )a  
        Returns
        =======

        reduced: list
            A list of the reduced monomials
        non_reduced: list
            A list of the monomials that are not reduced

        Definition
        ==========

        A polynomial is said to be reduced in x_i, if its degree (the
        maximum degree of its monomials) in x_i is less than d_i. A
        polynomial that is reduced in all variables but one is said
        simply to be reduced.
        c                    s&   g | ]\}}t | jd  k r|qS r7   r   r)   r   r   rr$   r   r   r         
z<MacaulayResultant.get_reduced_nonreduced.<locals>.<listcomp>c                    s&   g | ]\}}t | jd  kr|qS r   r   r   r$   r   r   r     r   )r~   	enumerater'   rB   boolr   ry   )r%   r   r*   rD   r   vreducednon_reducedr   r$   r   get_reduced_nonreduced  s   
 z(MacaulayResultant.get_reduced_nonreducedc                    s     \}}|g krtdgS fddtjD tfddtjD }|dd|f  g }t jD ] fdd|D }d|vrN| q9|||f S )a  
        Returns
        =======

        macaulay_submatrix: Matrix
            The Macaulay denominator matrix. Columns that are non reduced are kept.
            The row which contains one of the a_{i}s is dropped. a_{i}s
            are the coefficients of x_i ^ {d_i}.
        r7   c                    s   g | ]\}}| j |  qS r   )ry   )r   r   r   r$   r   r   r     rx   z3MacaulayResultant.get_submatrix.<locals>.<listcomp>c                    s    g | ]}j |  | qS r   )r"   Zcoeffr   )reduction_setr%   r   r   r     rJ   Nc                    s    g | ]}| d d f v qS r   r   )r   Zai)reduced_matrixrf   r   r   r     s     T)	r   r	   r   r'   r@   r+   r)   rC   rB   )r%   ra   r   r   Zaisr]   checkr   )r   r   rf   r%   r   get_submatrix  s"   



zMacaulayResultant.get_submatrixN)rr   rs   rt   ru   r/   rz   r|   r}   r   r   r   r   r   r   r   r   rw      s    .rw   N)ru   Zsympyr   r   r   r   r   r   r   r	   r
   Zsympy.polys.monomialsr   r   Zsympy.polys.orderingsr   Zsympy.polys.polytoolsr   r   Z(sympy.functions.combinatorial.factorialsr   	itertoolsr   Zsympy.utilities.exceptionsr   r   rw   r   r   r   r   <module>   s     ]