a
    <b;                     @   s   d Z ddlmZmZ ddlmZmZ ddlmZm	Z	m
Z
 ddlmZ ddl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.
    )Mulprod)Matrixdiag)Polydegree_listrem)simplify)IndexedBase)itermonomialsmonomial_deg)monomial_key)poly_from_exprtotal_degree)binomial)combinations_with_replacement)sympy_deprecation_warningc                   @   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 )DixonResultantaG  
    A class for retrieving the Dixon's resultant of a multivariate
    system.

    Examples
    ========

    >>> from sympy 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
        alphac                    s   g | ]} | qS  r   .0i)ar   s/Users/vegardjervell/Documents/master/model/venv/lib/python3.9/site-packages/sympy/polys/multivariate_resultants.py
<listcomp>W       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>Z   r   z5DixonResultant.__init__.<locals>.<listcomp>.<genexpr>)maxpolynomialsr   selfr    r   r   Z   s   N)	r#   	variableslennmr
   rangedummy_variables_max_degreesr&   r#   r'   r   )r   r&   r   __init__C   s    
zDixonResultant.__init__c                 C   s   t dddd | jS )NzS
            The max_degrees property of DixonResultant is deprecated.
            1.5$deprecated-dixonresultant-propertiesZdeprecated_since_versionZactive_deprecations_target)r   r-   r%   r   r   r   max_degrees]   s    zDixonResultant.max_degreesc                    s   | j | jd krtd| jg}t| j}t| jD ]B}| j| ||< dd t| j|D  |	 fdd| jD  q4t
|}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>   r   z7DixonResultant.get_dixon_polynomial.<locals>.<dictcomp>c                    s   g | ]}|  qS r   )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      r   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_polynomialh   s    
z#DixonResultant.get_dixon_polynomialc                    sB   t dddd  fddt jD }t|}t| }t| S )Nz
            The get_upper_degree() method of DixonResultant is deprecated. Use
            get_max_degrees() instead.
            r0   r1   r2   c                    s    g | ]} j |  j|  qS r   )r'   r-   r   r%   r   r   r      s   z3DixonResultant.get_upper_degree.<locals>.<listcomp>)r   r+   r)   r   r   Zmonomsr   )r&   Zlist_of_productsproductr   r%   r   get_upper_degree   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_2, \dots, 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   )coeffsr>   )r&   
polynomialZ	deg_listsr3   r   r%   r   get_max_degrees   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r 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      s   z>DixonResultant.get_dixon_matrix.<locals>.<listcomp>.<listcomp>r   r$   )	monomialsr&   )rO   r   r      s   z3DixonResultant.get_dixon_matrix.<locals>.<listcomp>r   r4   c                    s.   g | ]&}t d d  dd|f D r|qS )c                 s   s   | ]}|d kV  qdS r   Nr   )r   elementr   r   r   r!      r   z=DixonResultant.get_dixon_matrix.<locals>.<listcomp>.<genexpr>N)any)r   column)dixon_matrixr   r   r      s   N)	rI   r   r'   sortedr   r   rG   shaper+   )r&   rH   r3   keepr   )rU   rP   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 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 rQ   r   r   j)r   matrixr   r   r!      r   z=DixonResultant.KSY_precondition.<locals>.<listcomp>.<genexpr>)rS   r+   r$   r]   r)   r    r   r      r   z3DixonResultant.KSY_precondition.<locals>.<listcomp>Nr4   rV   T)is_zero_matrixrX   r	   Zrrefr+   r   )r&   r]   r*   r@   	conditionr   r^   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                    s   g | ]}  |js|qS r   )rowr_   r   r]   r   r   r      s   z?DixonResultant.delete_zero_rows_and_columns.<locals>.<listcomp>c                    s   g | ]}  |js|qS r   )colr_   r[   rc   r   r   r      s   )r+   r@   cols)r&   r]   r@   re   r   rc   r   delete_zero_rows_and_columns   s    

z+DixonResultant.delete_zero_rows_and_columnsc                 C   s<   d}t |jD ](}||D ]}|dkr|| } qqq|S )z;Calculate the product of the leading entries of the matrix.r4   r   )r+   r@   rb   )r&   r]   resrb   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.)rf   ZLUdecompositionr	   ri   )r&   r]   _Ur   r   r   get_KSY_Dixon_resultant   s    
z&DixonResultant.get_KSY_Dixon_resultantN)__name__
__module____qualname____doc__r/   propertyr3   rD   rF   rI   rZ   ra   rf   ri   rl   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 )MacaulayResultanta-  
    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 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   9  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
        r4   c                 s   s   | ]}|d  V  qdS )r4   Nr   )r   dr   r   r   r!   K  r   z2MacaulayResultant._get_degree_m.<locals>.<genexpr>)sumrs   r%   r   r   r   rt   B  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
        r4   )r   ru   r)   r%   r   r   r   rv   M  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   a  r   zEMacaulayResultant.get_monomials_of_certain_degree.<locals>.<listcomp>TrJ   rK   )r   r'   rW   r   )r&   degreerP   r   r   r   rw   Y  s    
z1MacaulayResultant.get_monomials_of_certain_degreec                    s   g }g }t | jD ]}|dkrD| j| j|  }| |}|| q|| j|d  | j|d    | j| j|  }| |}|D ].}|D ]$ t |dkr fdd|D }qq|| q|S )z
        Returns
        =======

        row_coefficients: list
            The row coefficients of Macaulay's matrix
        r   r4   c                    s   g | ]}| kr|qS r   r   )r   itempr   r   r     s   z:MacaulayResultant.get_row_coefficients.<locals>.<listcomp>)r+   r)   ru   rs   rw   r?   r'   r   )r&   row_coefficients	divisibler   r|   r{   Z	poss_rowsdivr   r~   r   get_row_coefficientsh  s$    

z&MacaulayResultant.get_row_coefficientsc           	      C   s|   g }|   }t| jD ]X}|| D ]J}g }t| j| | g| jR  }| jD ]}||| qL|| q"qt	|}|S )zt
        Returns
        =======

        macaulay_matrix: Matrix
            The Macaulay numerator matrix
        )
r   r+   r)   r   r#   r'   rx   r?   rN   r   )	r&   r@   r   r   
multiplierZcoefficientsr   ZmonoZmacaulay_matrixr   r   r   
get_matrix  s    
zMacaulayResultant.get_matrixc                    s   g } j D ]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 r4   rz   r)   r   r   rr%   r   r   r     s   z<MacaulayResultant.get_reduced_nonreduced.<locals>.<listcomp>c                    s&   g | ]\}}t | jd  kr|qS r   r   r   r%   r   r   r     s   )rx   	enumerater'   r?   boolr   rs   )r&   r   r*   rA   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rr| qr|||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}.
        r4   c                    s   g | ]\}}| j |  qS r   )rs   )r   r   r   r%   r   r   r     r   z3MacaulayResultant.get_submatrix.<locals>.<listcomp>c                    s    g | ]}j |  | qS r   )r#   Zcoeffr   )reduction_setr&   r   r   r     s   Nc                    s    g | ]}| d d f v qS r   r   )r   Zai)reduced_matrixrb   r   r   r     r   T)	r   r   r   r'   r=   r+   r)   r@   r?   )r&   r]   r   r   ZaisrY   checkr   )r   r   rb   r&   r   get_submatrix  s     


zMacaulayResultant.get_submatrixN)rm   rn   ro   rp   r/   rt   rv   rw   r   r   r   r   r   r   r   r   rr      s   .rr   N)rp   Zsympy.core.mulr   r   Zsympy.matrices.denser   r   Zsympy.polys.polytoolsr   r   r   Zsympy.simplify.simplifyr	   Zsympy.tensor.indexedr
   Zsympy.polys.monomialsr   r   Zsympy.polys.orderingsr   r   r   Z(sympy.functions.combinatorial.factorialsr   	itertoolsr   Zsympy.utilities.exceptionsr   r   rr   r   r   r   r   <module>   s    d