U
    ZÊ¹jÔ0  ã                   @   s°   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d	„Zdd
d„Ze	fdd„Ze	ddfdd„Ze	dfdd„Zdd„ Zdd„ Ze	dddfdd„ZdS )é    )ÚFunctionType)ÚCoercionFailed)ÚZZÚQQé   )Ú_get_intermediate_simpÚ_iszeroÚ_dotprodsimpÚ	_simplify)Ú_find_reasonable_pivotTc	                    sD  ‡ ‡fdd„}	‡ ‡fdd„}
‡ ‡‡fdd„}t tƒ‰d\}}g }g }|ˆ k �r°||k �r°t|	|ƒ|d… ||ƒ\}}}}|D ] \}}||7 }|ˆ|ˆ  | < q||dkr°|d	7 }qD| |¡ |d
krâ|
||| ƒ | ||| f¡ |dk�rD|| }}|ˆ|ˆ  | < t|ˆ  | d	 |d	 ˆ  ƒD ]}ˆˆ| | ƒˆ|< �q$|}t|ƒD ]X}||k�r^�qL|dk�rv||k �rv�qLˆ|ˆ  |  }||ƒ�r”�qL|||||ƒ �qL|d	7 }qD|dk�r2|dk�r2t|ƒD ]d\}}ˆ|ˆ  |  }|ˆ|ˆ  | < t|ˆ  | d	 |d	 ˆ  ƒD ]}ˆˆ| | ƒˆ|< �q�qÌˆt|ƒt|ƒfS )aÛ  Row reduce a flat list representation of a matrix and return a tuple
    (rref_matrix, pivot_cols, swaps) where ``rref_matrix`` is a flat list,
    ``pivot_cols`` are the pivot columns and ``swaps`` are any row swaps that
    were used in the process of row reduction.

    Parameters
    ==========

    mat : list
        list of matrix elements, must be ``rows`` * ``cols`` in length

    rows, cols : integer
        number of rows and columns in flat list representation

    one : SymPy object
        represents the value one, from ``Matrix.one``

    iszerofunc : determines if an entry can be used as a pivot

    simpfunc : used to simplify elements and test if they are
        zero if ``iszerofunc`` returns `None`

    normalize_last : indicates where all row reduction should
        happen in a fraction-free manner and then the rows are
        normalized (so that the pivots are 1), or whether
        rows should be normalized along the way (like the naive
        row reduction algorithm)

    normalize : whether pivot rows should be normalized so that
        the pivot value is 1

    zero_above : whether entries above the pivot should be zeroed.
        If ``zero_above=False``, an echelon matrix will be returned.
    c                    s   ˆ| d ˆ … S ©N© ©Úi©ÚcolsÚmatr   úX/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/matrices/reductions.pyÚget_col/   s    z!_row_reduce_list.<locals>.get_colc                    s^   ˆ|ˆ  |d ˆ  … ˆ| ˆ  | d ˆ  …  ˆ| ˆ  | d ˆ  …< ˆ|ˆ  |d ˆ  …< d S )Nr   r   )r   Újr   r   r   Úrow_swap2   s    .ÿz"_row_reduce_list.<locals>.row_swapc                    sP   || ˆ  }t |ˆ  |d ˆ  ƒD ](}ˆ| ˆ|  |ˆ||    ƒˆ|< q"dS )z,Does the row op row[i] = a*row[i] - b*row[j]r   N)Úrange)Úar   Úbr   ÚqÚp©r   Zisimpr   r   r   Úcross_cancel6   s    z&_row_reduce_list.<locals>.cross_cancel©r   r   Nr   r   FT)r   r	   r   Úappendr   Ú	enumerateÚtuple)r   Úrowsr   ÚoneÚ
iszerofuncÚsimpfuncÚnormalize_lastÚ	normalizeÚ
zero_abover   r   r   Zpiv_rowZpiv_colÚ
pivot_colsÚswapsZpivot_offsetZ	pivot_valZassumed_nonzeroZnewly_determinedÚoffsetÚvalr   r   r   ÚrowZpiv_iZpiv_jr   r   r   Ú_row_reduce_list
   sb    %  ÿÿ 


"


"r.   c           	      C   sB   t t| ƒ| j| j| j|||||d�	\}}}|  | j| j|¡||fS )N©r&   r'   r(   )r.   Úlistr"   r   r#   Ú_new)	ÚMr$   r%   r&   r'   r(   r   r)   r*   r   r   r   Ú_row_reduce|   s       þr3   c                    s‚   | j dks| jdkrdS t‡ fdd„| dd…df D ƒƒ}ˆ | d ƒrd|obt| dd…dd…f ˆ ƒS |o€t| dd…dd…f ˆ ƒS )z¦Returns `True` if the matrix is in echelon form. That is, all rows of
    zeros are at the bottom, and below each leading non-zero in a row are
    exclusively zeros.r   Tc                 3   s   | ]}ˆ |ƒV  qd S r   r   )Ú.0Út©r$   r   r   Ú	<genexpr>Ž   s     z_is_echelon.<locals>.<genexpr>r   Nr   )r"   r   ÚallÚ_is_echelon)r2   r$   Zzeros_belowr   r6   r   r9   †   s    "r9   Fc                 C   s<   t |tƒr|nt}t| ||dddd�\}}}|r8||fS |S )an  Returns a matrix row-equivalent to ``M`` that is in echelon form. Note
    that echelon form of a matrix is *not* unique, however, properties like the
    row space and the null space are preserved.

    Examples
    ========

    >>> from sympy import Matrix
    >>> M = Matrix([[1, 2], [3, 4]])
    >>> M.echelon_form()
    Matrix([
    [1,  2],
    [0, -2]])
    TFr/   )Ú
isinstancer   r
   r3   )r2   r$   ÚsimplifyZwith_pivotsr%   r   ÚpivotsÚ_r   r   r   Ú_echelon_form–   s      ÿr>   c           
         sü   dd„ }t |tƒr|nt}| jdks.| jdkr2dS | jdksF| jdkrd‡ fdd„| D ƒ}d|krddS | jdkrÊ| jdkrÊ‡ fd	d„| D ƒ}d|kržd
|krždS |  ¡ }ˆ |ƒrºd|krºdS ˆ |ƒdkrÊdS || ˆ d�\}}t|ˆ |dddd�\}}	}t|	ƒS )zÿReturns the rank of a matrix.

    Examples
    ========

    >>> from sympy import Matrix
    >>> from sympy.abc import x
    >>> m = Matrix([[1, 2], [x, 1 - 1/x]])
    >>> m.rank()
    2
    >>> n = Matrix(3, 3, range(1, 10))
    >>> n.rank()
    2
    c                    sJ   ‡ ‡fdd„‰‡fdd„t ˆ jƒD ƒ}dd„ t|ƒD ƒ}ˆ j|dd�|fS )a€  Permute columns with complicated elements as
        far right as they can go.  Since the ``sympy`` row reduction
        algorithms start on the left, having complexity right-shifted
        speeds things up.

        Returns a tuple (mat, perm) where perm is a permutation
        of the columns to perform to shift the complex columns right, and mat
        is the permuted matrix.c                    s"   t ‡fdd„ˆ d d …| f D ƒƒS )Nc                 3   s"   | ]}ˆ |ƒd krdndV  qd S )Nr   r   r   ©r4   Úer6   r   r   r7   Ï   s     zO_rank.<locals>._permute_complexity_right.<locals>.complexity.<locals>.<genexpr>)Úsumr   )r2   r$   r   r   Ú
complexityÌ   s    z<_rank.<locals>._permute_complexity_right.<locals>.complexityc                    s   g | ]}ˆ |ƒ|f‘qS r   r   )r4   r   )rB   r   r   Ú
<listcomp>Ñ   s     z<_rank.<locals>._permute_complexity_right.<locals>.<listcomp>c                 S   s   g | ]\}}|‘qS r   r   )r4   r   r   r   r   r   rC   Ò   s     r   )Zorientation)r   r   ÚsortedZpermute)r2   r$   ÚcomplexÚpermr   )r2   rB   r$   r   Ú_permute_complexity_rightÂ   s    
z(_rank.<locals>._permute_complexity_rightr   r   c                    s   g | ]}ˆ |ƒ‘qS r   r   ©r4   Úxr6   r   r   rC   ß   s     z_rank.<locals>.<listcomp>Fé   c                    s   g | ]}ˆ |ƒ‘qS r   r   rH   r6   r   r   rC   å   s     Nr6   Tr/   )r:   r   r
   r"   r   Zdetr3   Úlen)
r2   r$   r;   rG   r%   ZzerosÚdr   r=   r<   r   r6   r   Ú_rank²   s.    
 ÿrM   c                 C   s˜   t | dƒsd S | j}|j}|jr$|S |jrRz| t¡W S  tk
rN   | Y S X nBtdd„ | D ƒƒshd S z| t¡W S  tk
r’   | t	¡ Y S X d S )NÚ_repc                 s   s   | ]}|j V  qd S r   )Zis_Rationalr?   r   r   r   r7     s     z_to_DM_ZZ_QQ.<locals>.<genexpr>)
ÚhasattrrN   ÚdomainÚis_ZZÚis_QQZ
convert_tor   r   r8   r   )r2   ÚrepÚKr   r   r   Ú_to_DM_ZZ_QQø   s"    
rU   c                 C   sX   | j }|jr,| jdd�\}}}| ¡ | }n|jr@|  ¡ \}}ndsHt‚| ¡ }||fS )z7Compute the reduced row echelon form of a DomainMatrix.F)Zkeep_domain)rP   rQ   Zrref_denZto_fieldrR   ZrrefÚAssertionErrorZ	to_Matrix)ÚdMrT   ZdM_rrefZdenr<   ZM_rrefr   r   r   Ú_rref_dm  s    rX   c           
      C   s`   t | ƒ}|dk	rt|ƒ\}}n.t|tƒr.|}nt}t| |||ddd�\}}}	|rX||fS |S dS )a-	  Return reduced row-echelon form of matrix and indices
    of pivot vars.

    Parameters
    ==========

    iszerofunc : Function
        A function used for detecting whether an element can
        act as a pivot.  ``lambda x: x.is_zero`` is used by default.

    simplify : Function
        A function used to simplify elements when looking for a pivot.
        By default SymPy's ``simplify`` is used.

    pivots : True or False
        If ``True``, a tuple containing the row-reduced matrix and a tuple
        of pivot columns is returned.  If ``False`` just the row-reduced
        matrix is returned.

    normalize_last : True or False
        If ``True``, no pivots are normalized to `1` until after all
        entries above and below each pivot are zeroed.  This means the row
        reduction algorithm is fraction free until the very last step.
        If ``False``, the naive row reduction procedure is used where
        each pivot is normalized to be `1` before row operations are
        used to zero above and below the pivot.

    Examples
    ========

    >>> from sympy import Matrix
    >>> from sympy.abc import x
    >>> m = Matrix([[1, 2], [x, 1 - 1/x]])
    >>> m.rref()
    (Matrix([
    [1, 0],
    [0, 1]]), (0, 1))
    >>> rref_matrix, rref_pivots = m.rref()
    >>> rref_matrix
    Matrix([
    [1, 0],
    [0, 1]])
    >>> rref_pivots
    (0, 1)

    ``iszerofunc`` can correct rounding errors in matrices with float
    values. In the following example, calling ``rref()`` leads to
    floating point errors, incorrectly row reducing the matrix.
    ``iszerofunc= lambda x: abs(x) < 1e-9`` sets sufficiently small numbers
    to zero, avoiding this error.

    >>> m = Matrix([[0.9, -0.1, -0.2, 0], [-0.8, 0.9, -0.4, 0], [-0.1, -0.8, 0.6, 0]])
    >>> m.rref()
    (Matrix([
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0]]), (0, 1, 2))
    >>> m.rref(iszerofunc=lambda x:abs(x)<1e-9)
    (Matrix([
    [1, 0, -0.301369863013699, 0],
    [0, 1, -0.712328767123288, 0],
    [0, 0,         0,          0]]), (0, 1))

    Notes
    =====

    The default value of ``normalize_last=True`` can provide significant
    speedup to row reduction, especially on matrices with symbols.  However,
    if you depend on the form row reduction algorithm leaves entries
    of the matrix, set ``normalize_last=False``
    NT)r'   r(   )rU   rX   r:   r   r
   r3   )
r2   r$   r;   r<   r&   rW   r   r)   r%   r=   r   r   r   Ú_rref'  s    J
  ÿrY   N)TTT)TTT)Útypesr   Zsympy.polys.polyerrorsr   Zsympy.polys.domainsr   r   Z	utilitiesr   r   r	   r
   Zdeterminantr   r.   r3   r9   r>   rM   rU   rX   rY   r   r   r   r   Ú<module>   s(        ÿ
r    ÿ

Fÿ