B
    T\ګ                 @   sr  d dl mZmZmZ d dlZd dlmZ d dlmZ d dl	Z
d dl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mZ d
dlmZ d
dlmZ dd Zdd Zdd Zdd Zd=ddZd>ddZ d?ddZ!d@dd Z"dAd!d"Z#d#d$ Z$d%d& Z%d'd( Z&d)d* Z'dBd+d,Z(dCd-d.Z)d/d0 Z*d1d2 Z+dDd3d4Z,d5d6 Z-d7d8 Z.d9d: Z/ee
j0j1dEd;d<Z1dS )F    )absolute_importdivisionprint_functionN)wraps)Number   )tokenize)	blockwise)apply)HighLevelGraph   )dotmanyArrayconcatenate)eye)RandomStatec             c   s,   d}x"| D ]}|}||7 }||fV  q
W d S )Nr    )itZtotalxZtotal_previousr   r   0lib/python3.7/site-packages/dask/array/linalg.py_cumsum_blocks   s
    
r   c             C   s   | d | d | fS )Nr   r   )Zlastnewr   r   r   _cumsum_part   s    r   c             C   s0   t | |g}t|r| n|}t|r,|S |S )N)minnpisnan)mnZk_0Zk_1r   r   r   _nanmin   s    r   c             C   s<   | j d dkr,tdtd| j d ffS tj| S dS )z
    A wrapper for np.linalg.qr that handles arrays with 0 rows

    Notes: Created for tsqr so as to manage cases with uncertain
    array dimensions. In particular, the case where arrays have
    (uncertain) chunks with 0 rows.
    r   )r   r   r   N)shaper   zeroslinalgqr)ar   r   r   _wrapped_qr%   s    	r$   Fc       U         sp
  t  jd t  jd  }}t jd  jd d  }} jdkrN|dksbtd j jdt | } j\}|df}	t	j
t	jd jd\}
}  j }  j }d| 	tt	d	 jd	 j|	id
}||	<   |	< d| d t	fddt|	d D }||< 	h|< d| d 
t	
fddt|	d D }||
< 	h|
< || }tdd  jD  }t	|| }|dkr|n|d| k}|ot|dk}|r|r|rg }g }d}xdt jd D ]R\}}|}t||}|}|| |kr.|| g }d}|||f ||7 }qW t |dkrb|| d| d t
fddt|D }||< 
h|< tdd |D }t||} t | t!|f|f|jd}!t"|!|d\}"t#$j%j|"j%j}t#$j%j|"j%j}d| d tfddt|D }#|#|<  |< d| }$|$ddf|"jddfi}%|%||$< |" ||$< d| d }&tt	j&|&d	d	d	|	|	id
}'|'||&< |&h||&< nއ
fddt|	d D }(d| d })|)ddft	j't|(ffi}*|*||)< 
h||)< d| d  }+tt	j
j|+d	|)d	|)did
},|,||+< |)h||+< d| d! ddft(j)|+ddfdfi}-|-|< |+h|< td"d  jD s܇fd#d jd D }.fd$dt*|.D }/i }0t+ }1nd%| d  fd&d't|	d D }2d| d( t(j)t, jddfd%fdfi}3d)| d dfddfgi}4|4-fd*d'td|	d D  d+| d, fd-d't|	d D }5t#$|3|2|4|5}0 jh}1fd.dt|	d D }/|0|d/| < |1|d/| < d| d tfd0dt|/D }#|#|< d/| h|< d1| d }&tt	j&|&d	d	d	|	|	id
}'|'||&< h||&< d| d2 }$|$ddft(j)|+ddfdfi}%|%||$< |+h||$< |szt	. jd ptd3d  jd D }6t	. jd ptd4d  jd D }7|6rB|7rB j}8 jd t	j/ff}9t	j/t	j/f}:t	j/ft	j/ff};n|6rv|7sv j}8 jd ff}9f}:f};n|6s|7r j}8 jd t	j/ff}9t	j/t	j/f}:t	j/ft	j/ff};n jd  jd krԈ jn jd  jd f}8 jd  jd kr jn jd  jd f}9 jd  jd kr6fn j}:|:};t||} t | |&|8|9|
jd}<t | |$|:|;|jd}=|<|=fS d5| d6 }>tt	j
j0|>d	|$d	|$did
}?d| d7 }@|@ddft(j)|>ddfdfi}Ad| d8 }B|Bdft(j)|>ddfdfi}Cd| d9 }D|Dddft(j)|>ddfdfi}Ed| d: }Ftt1|Fd	|&d;|@d<|&|	|@did
}G|?||>< |$h||>< |A||@< |>h||@< |G||F< |&|@h||F< |C||B< |>h||B< |E||D< |>h||D< t	j
0t	jd jd\}H}I}Jt2|}K|}Lt	.|K	st|Kn|K}M|M}N|M}O}Pt|O|P}Qt||} t | |F|L|Mf jd |Mff|Hjd}Rt | |B|Nf|Nff|Ijd}St | |D|Q|Qffff|Jjd}T|R|S|TfS dS )=a   Direct Tall-and-Skinny QR algorithm

    As presented in:

        A. Benson, D. Gleich, and J. Demmel.
        Direct QR factorizations for tall-and-skinny matrices in
        MapReduce architectures.
        IEEE International Conference on Big Data, 2013.
        http://arxiv.org/abs/1301.1071

    This algorithm is used to compute both the QR decomposition and the
    Singular Value Decomposition.  It requires that the input array have a
    single column of blocks, each of which fit in memory.

    Parameters
    ----------
    data: Array
    compute_svd: bool
        Whether to compute the SVD rather than the QR decomposition
    _max_vchunk_size: Integer
        Used internally in recursion to set the maximum row dimension
        of chunks in subsequent recursive calls.

    Notes
    -----
    With ``k`` blocks of size ``(m, n)``, this algorithm has memory use that
    scales as ``k * m * n``.

    The implementation here is the recursive variant due to the ultimate
    need for one "single core" QR decomposition. In the non-recursive version
    of the algorithm, given ``k`` blocks, after ``k`` ``m * n`` QR
    decompositions, there will be a "single core" QR decomposition that will
    have to work with a ``(k * n, n)`` matrix.

    Here, recursion is applied as necessary to ensure that ``k * n`` is not
    larger than ``m`` (if ``m / n >= 2``). In particular, this is done
    to ensure that single core computations do not have to work on blocks
    larger than ``(m, n)``.

    Where blocks are irregular, the above logic is applied with the "height" of
    the "tallest" block used in place of ``m``.

    Consider use of the ``rechunk`` method to control this behavior. Blocks
    that are as tall as possible are recommended.

    See Also
    --------
    dask.array.linalg.qr - Powered by this algorithm
    dask.array.linalg.svd - Powered by this algorithm
    dask.array.linalg.sfqr - Variant for short-and-fat arrays
    r   r   r   a  Input must have the following properties:
  1. Have two dimensions
  2. Have only one column of blocks

Note: This function (tsqr) supports QR decomposition in the case of
tall-and-skinny matrices (single column chunk/block; see qr)Current shape: {},
Current chunksize: {}-)r   r   )r   dtyper"   Zij)	numblocksgetitemz-q1c             3   s*   | ]"} |d ft j|d fd ffV  qdS )r   N)operatorr(   ).0i)
name_q_st1name_qr_st1r   r   	<genexpr>   s   ztsqr.<locals>.<genexpr>z-r1c             3   s*   | ]"}|d ft j |d fdffV  qdS )r   r   N)r)   r(   )r*   r+   )r-   
name_r_st1r   r   r.      s   c             s   s"   | ]}|D ]}t |V  q
qd S )N)r   r   )r*   cscr   r   r   r.      s    Nstackc             3   s8   | ]0\}}|d ft jt fdd|D fffV  qdS )r   c                s   g | ]\}} |d fqS )r   r   )r*   idx_)r/   r   r   
<listcomp>   s   z"tsqr.<locals>.<genexpr>.<listcomp>N)r   vstacktuple)r*   r+   sub_block_info)r/   name_r_stackedr   r   r.      s   c             S   s   g | ]}t td d |qS )c             S   s   | d S )Nr   r   )r   r   r   r   <lambda>   s    z!tsqr.<locals>.<listcomp>.<lambda>)summap)r*   r8   r   r   r   r5      s    ztsqr.<locals>.<listcomp>)r   chunksr&   )_max_vchunk_sizezgetitem-z-q2c          	   3   st   | ]l\}}t d d |D tdd |D D ]@\}}|dftjj|dft|d |d td fffV  q,qdS )c             S   s   g | ]}|d  qS )r   r   )r*   r   r   r   r   r5      s    z"tsqr.<locals>.<genexpr>.<listcomp>c             S   s   g | ]}|d  qS )r   r   )r*   r   r   r   r   r5      s    r   r   N)zipr   r)   r(   nameslice)r*   r+   r8   je)r   
name_q_st2q_innerr   r   r.      s   zr-inner-zdot-z-q3c                s   g | ]} |d fqS )r   r   )r*   r+   )r/   r   r   r5      s    z-qr2z-q2-auxc             s   s"   | ]}|D ]}t |V  q
qd S )N)r   r   )r*   r0   r1   r   r   r   r.      s    c                s   g | ]}t | qS r   )r   )r*   rC   )r   r   r   r5     s    c                s(   g | ] }t |d  |d t d  fqS )r   r   )rA   )r*   rC   )r   r   r   r5     s   r   c                s(   i | ] }t t j|d fdff|fqS )r   r   )r   getattrr@   )r*   r+   )data	name_q2bsr   r   
<dictcomp>  s   ztsqr.<locals>.<dictcomp>z-nZcumsumc                s(   i | ] }t |d  f |ff|fqS )r   )r   )r*   r+   )rH   	name_q2csr   r   rI     s   rA   z-qc                s.   i | ]&}t tt|fftd fgf |fqS )r   )r7   r
   rA   )r*   r+   )name_blockslicename_nrJ   r   r   rI     s   c                s   g | ]} |fqS r   r   )r*   r+   )rK   r   r   r5   &  s    zq-blocksizesc             3   s.   | ]&\}} |d ft jd d f|ffV  qdS )r   N)r)   r(   )r*   r+   b)rD   name_q_st2_auxr   r   r.   -  s   dotz-r2c             s   s   | ]}t |V  qd S )N)r   r   )r*   r1   r   r   r   r.   B  s    c             s   s   | ]}t |V  qd S )N)r   r   )r*   r1   r   r   r   r.   C  s    svdz-2z-u2z-s2z-v2z-u4ZikZkj)3lenr=   maxndim
ValueErrorformatr   Z	chunksizer   r   r!   r"   onesr&   __dask_graph__layerscopydependenciesr	   r$   r@   __dask_layers__dictrangeanyZceilint	enumerater   appendr7   r   r   r;   tsqrtoolzmergeZdaskrO   r6   r)   r(   r   setrF   updater   nanrP   r   r   )UrG   compute_svdr>   nrncZcr_maxcctokenr   r'   qqrrrX   rZ   Z
dsk_qr_st1Z	dsk_q_st1Z	dsk_r_st1Zsingle_core_compute_mZchunks_well_definedZprospective_blocksZmeaningful_reduction_possibleZcan_distributeZ
all_blocksZ
curr_blockZcurr_block_szr3   Za_mZm_qZn_qZm_rZdsk_r_stackedZvchunks_rstackedgraphZ	r_stackedZr_innerZ	dsk_q_st2Z
name_r_st2Z	dsk_r_st2Z
name_q_st3Z	dsk_q_st3Zto_stackZname_r_st1_stackedZdsk_r_st1_stackedZname_qr_st2Z
dsk_qr_st2Zdsk_q_st2_auxZq2_block_sizesZblock_slicesZdsk_q_blockslicesZdepsZdsk_q2_shapesZdsk_nZdsk_q2_cumsumZdsk_block_slicesZis_unknown_mZis_unknown_nZq_shapeZq_chunksZr_shapeZr_chunksqrZname_svd_st2Zdsk_svd_st2Z
name_u_st2Z	dsk_u_st2Z
name_s_st2Z	dsk_s_st2Z
name_v_st2Z	dsk_v_st2Z
name_u_st4Z	dsk_u_st4uussZvvhkZm_uZn_uZn_sZm_vhZn_vhZd_vhusZvhr   )rG   r   rK   rL   rH   rJ   r,   rD   rN   r-   r/   r9   rE   r   rb   4   s   4













**
00$








$ rb   c                sv  t  jd t  jd  }} jd d  jd d  }} jdkr^|dkr^||ksf|dksftd|ptdt  }|d7 } j\}}tjtj	d j
d\}	}
  j }  j }|d	 }|d
 |ddf jddfi||<   ||<  fddt|d D |<   |< |d }|d }|d }|ddftjj|ddffi||< |h||< |ddftj|ddfdfi||< |h||< |ddftj|ddfdfi||< |h||< t||}t|||t||f|t||f|	j
d}t||t|||f||f|
j
d}|g}|dkrbt|t|||| f| jd dd f|
j
d}||j| t|dd}||fS )a$   Direct Short-and-Fat QR

    Currently, this is a quick hack for non-tall-and-skinny matrices which
    are one chunk tall and (unless they are one chunk wide) have chunks
    that are wider than they are tall

    Q [R_1 R_2 ...] = [A_1 A_2 ...]

    it computes the factorization Q R_1 = A_1, then computes the other
    R_k's in parallel.

    Parameters
    ----------
    data: Array

    See Also
    --------
    dask.array.linalg.qr - Main user API that uses this function
    dask.array.linalg.tsqr - Variant for tall-and-skinny case
    r   r   r   a  Input must have the following properties:
  1. Have two dimensions
  2. Have only one row of blocks
  3. Either one column of blocks or (first) chunk size on cols
     is at most that on rows (e.g.: for a 5x20 matrix,
     chunks=((5), (8,4,8)) is fine, but chunks=((5), (4,8,8)) is not;
     still, prefer something simple like chunks=(5,10) or chunks=5)

Note: This function (sfqr) supports QR decomposition in the case
of short-and-fat matrices (single row chunk/block; see qr)zsfqr-r4   )r   r   )r   r&   ZA_1A_restc                s$   i | ]} j d d| fd |fqS )r   r   )r@   )r*   r3   )rG   name_A_restr   r   rI     s   zsfqr.<locals>.<dictcomp>ZQ_R_1QR_1)r   r=   r&   N)axis)rQ   r=   rS   rT   r   r   r   r!   r"   rV   r&   rW   rX   rY   rZ   r@   r[   r]   r)   r(   r   r   r   ra   TrO   r   )rG   r@   ri   rj   Zcrrk   prefixr   r   rm   rn   rX   rZ   Zname_A_1Z	name_Q_R1Zname_QZname_R_1ro   ry   rz   ZRsrw   Rr   )rG   rx   r   sfqr  sT    

 
 
 

"
.r   
      c             C   s   t t||| | S )a    Compression level to use in svd_compressed

    Given the size ``n`` of a space, compress that that to one of size
    ``q`` plus oversampling.

    The oversampling allows for greater flexibility in finding an
    appropriate subspace, a low value is often enough (10 is already a
    very conservative choice, it can be further reduced).
    ``q + oversampling`` should not be larger than ``n``.  In this
    specific implementation, ``q + oversampling`` is at least
    ``min_subspace_size``.

    >>> compression_level(100, 10)
    20
    )r   rR   )r   rp   ZoversamplingZmin_subspace_sizer   r   r   compression_level  s    r   c             C   sz   | j d }t||}t|}|j||f| jd |ffd}| |}x"t|D ]}	| | j|}qNW t|\}}
|jS )a`   Randomly sample matrix to find most active subspace

    This compression matrix returned by this algorithm can be used to
    compute both the QR decomposition and the Singular Value
    Decomposition.

    Parameters
    ----------
    data: Array
    q: int
        Size of the desired subspace (the actual size will be bigger,
        because of oversampling, see ``da.linalg.compression_level``)
    n_power_iter: int
        number of power iterations, useful when the singular values of
        the input matrix decay very slowly.

    References
    ----------
    N. Halko, P. G. Martinsson, and J. A. Tropp.
    Finding structure with randomness: Probabilistic algorithms for
    constructing approximate matrix decompositions.
    SIAM Rev., Survey and Review section, Vol. 53, num. 2,
    pp. 217-288, June 2011
    http://arxiv.org/abs/0909.4061
    r   )sizer=   )	r   r   r   Zstandard_normalr=   rO   r]   r|   rb   )rG   rp   n_power_iterseedr   Z
comp_levelstateZomegaZmat_hrB   r4   r   r   r   compression_matrix  s    


r   c       	      C   s~   t | |||d}|| }t|jdd\}}}|j|}|j}|ddd|f }|d| }|d|ddf }|||fS )a   Randomly compressed rank-k thin Singular Value Decomposition.

    This computes the approximate singular value decomposition of a large
    array.  This algorithm is generally faster than the normal algorithm
    but does not provide exact results.  One can balance between
    performance and accuracy with input parameters (see below).

    Parameters
    ----------
    a: Array
        Input array
    k: int
        Rank of the desired thin SVD decomposition.
    n_power_iter: int
        Number of power iterations, useful when the singular values
        decay slowly. Error decreases exponentially as n_power_iter
        increases. In practice, set n_power_iter <= 4.

    Examples
    --------

    >>> u, s, vt = svd_compressed(x, 20)  # doctest: +SKIP

    Returns
    -------
    u:  Array, unitary / orthogonal
    s:  Array, singular values in decreasing order (largest first)
    v:  Array, unitary / orthogonal

    References
    ----------
    N. Halko, P. G. Martinsson, and J. A. Tropp.
    Finding structure with randomness: Probabilistic algorithms for
    constructing approximate matrix decompositions.
    SIAM Rev., Survey and Review section, Vol. 53, num. 2,
    pp. 217-288, June 2011
    http://arxiv.org/abs/0909.4061
    )r   r   T)rh   N)r   rO   rb   r|   )	r#   rt   r   r   compZa_compressedvrv   ru   r   r   r   svd_compressed-  s    '
r   c             C   sR   t | jd dkr,t | jd dkr,t| S t | jd dkrFt| S tddS )a  
    Compute the qr factorization of a matrix.

    Examples
    --------

    >>> q, r = da.linalg.qr(x)  # doctest: +SKIP

    Returns
    -------

    q:  Array, orthonormal
    r:  Array, upper-triangular

    See Also
    --------

    np.linalg.qr : Equivalent NumPy Operation
    dask.array.linalg.tsqr: Implementation for tall-and-skinny arrays
    dask.array.linalg.sfqr: Implementation for short-and-fat arrays
    r   r   a}  qr currently supports only tall-and-skinny (single column chunk/block; see tsqr)
and short-and-fat (single row chunk/block; see sfqr) matrices

Consider use of the rechunk method. For example,

x.rechunk({0: -1, 1: 'auto'}) or x.rechunk({0: 'auto', 1: -1})

which rechunk one shorter axis to a single chunk, while allowing
the other axis to automatically grow/shrink appropriately.N)rQ   r=   rb   r   NotImplementedError)r#   r   r   r   r"   _  s    $r"   c             C   s   t | ddS )a  
    Compute the singular value decomposition of a matrix.

    Examples
    --------

    >>> u, s, v = da.linalg.svd(x)  # doctest: +SKIP

    Returns
    -------

    u:  Array, unitary / orthogonal
    s:  Array, singular values in decreasing order (largest first)
    v:  Array, unitary / orthogonal

    See Also
    --------

    np.linalg.svd : Equivalent NumPy Operation
    dask.array.linalg.tsqr: Implementation for tall-and-skinny arrays
    T)rh   )rb   )r#   r   r   r   rP     s    rP   c             C   s   dd l }|jj| |ddS )Nr   T)lower)scipy.linalgr!   solve_triangular)r#   rM   scipyr   r   r   _solve_triangular_lower  s    r   c             C   sz  ddl }| jdkrtd| j\}}||kr4tdtt| jd | jd  dks`d}t|t| jd }t| jd }t| }d| }d	| }	d
| }
d| }d| }d| }d| }d| }d| }i }xtt	||D ]}| j
||f}|dkrZg }xFt|D ]:}|||||f}tj|||f|||ff||< || qW tj|t|ff}|jj|f||||f< xt|d |D ]}tj|||f| j
||ff}|dkrg }xFt|D ]:}|||||f}tj|
||f|||ff||< || qW tj|t|ff}t|
||f|f||||f< qW xt|d |D ]}| j
||f}|dkrg }xFt|D ]:}|||||f}tj|||f|||ff||< || q\W tj|t|ff}tjt|||ftj|fff||||f< q4W qW xtt	||D ]}xtt	||D ]}||krtj|||fdf||	||f< tj|||fdf||
||f< tj|||fdf||||f< tj|	||f|
||ff||||f< tj|||ff||||f< tj|	||ff||||f< q||kr\tj| jd | | jd | ff||	||f< tj|||f|||ff||
||f< tj| jd | | jd | ff||||f< |||f||||f< nltj| jd | | jd | ff||	||f< tj| jd | | jd | ff||
||f< |||f||||f< qW qW |jtjd| jd\}}}tj|	|| gd}t||	| j| j|jd}tj|
|| gd}t||
| j| j|jd}tj||| gd}t||| j| j|jd}|||fS )a!  
    Compute the lu decomposition of a matrix.

    Examples
    --------

    >>> p, l, u = da.linalg.lu(x)  # doctest: +SKIP

    Returns
    -------

    p:  Array, permutation matrix
    l:  Array, lower triangular matrix with unit diagonal.
    u:  Array, upper triangular matrix
    r   Nr   z/Dimension must be 2 to perform lu decompositionz9Input must be a square matrix to perform lu decompositionr   zqAll chunks must be a square matrix to perform lu decomposition. Use .rechunk method to change the size of chunks.zlu-lu-zlu-p-zlu-l-zlu-u-z	lu-p-inv-zlu-l-permute-zlu-u-transpose-zlu-plu-dot-z
lu-lu-dot-)r   r   )r   r&   )rZ   )r   r=   r&   )r   rS   rT   r   rQ   re   r=   r   r]   r   r@   r   rO   ra   r)   subr;   r!   lur   	transposer(   r    rV   r&   r   from_collectionsr   )r#   r   xdimydimmsgvdimhdimrl   Zname_luZname_pZname_lZname_uZ
name_p_invZname_l_permutedZname_u_transposedZname_plu_dotZname_lu_dotdskr+   targetprevspprevrB   rt   ZppZllrr   ro   lru   r   r   r   r     s    

 


"
"
,",,, r   c                s  ddl }| jdkrtd jdkrb| jd  jd kr@td| jd  jd krjd}t|ntdt| jd } jdkrdnt jd }t|  |}d	| d
| } fdd}	 fdd}
i }|rxt|D ]}xt|D ]}|	||}|dkrbg }xHt|D ]<}|||||f}tj	| j
||f|
||f||< || qW tj|t|ff}t| j
||f|f||
||< qW qW nxt|D ]}xt|D ]}|	||}||d k r g }xNt|d |D ]<}|||||f}tj	| j
||f|
||f||< || qW tj|t|ff}|jj| j
||f|f||
||< qW qW tj||  gd}ttjddgddgg| jdtjddg jd}t| j j|jdS )a  
    Solve the equation `a x = b` for `x`, assuming a is a triangular matrix.

    Parameters
    ----------
    a : (M, M) array_like
        A triangular matrix
    b : (M,) or (M, N) array_like
        Right-hand side matrix in `a x = b`
    lower : bool, optional
        Use only data contained in the lower triangle of `a`.
        Default is to use upper triangle.

    Returns
    -------
    x : (M,) or (M, N) array
        Solution to the system `a x = b`. Shape of return matches `b`.
    r   Nr   za must be 2 dimensionalr   z'a.shape[1] and b.shape[0] must be equalz\a.chunks[1] and b.chunks[0] must be equal. Use .rechunk method to change the size of chunks.zb must be 1 or 2 dimensionalzsolve-triangular-zsolve-tri-dot-c                s$    j dkr j| fS  j| |fS d S )Nr   )rS   r@   )r+   rB   )rM   r   r   _b_initO  s    

z!solve_triangular.<locals>._b_initc                s     j dkr| fS | |fS d S )Nr   )rS   )r+   rB   )rM   r@   r   r   _keyU  s    
zsolve_triangular.<locals>._key)rZ   )r&   )r   r=   r&   )r   rS   rT   r   r=   rQ   r   r]   r   rO   r@   ra   r)   r   r;   r   r!   r   r   r   arrayr&   r   )r#   rM   r   r   r   ZvchunksZhchunksrl   Z	name_mdotr   r   r   r+   rB   r   r   rt   r   ro   Zresr   )rM   r@   r   r   $  sZ    




&
,r   c             C   sD   |rt | \}}nt| \}}}|j|}t||dd}t||S )aq  
    Solve the equation ``a x = b`` for ``x``. By default, use LU
    decomposition and forward / backward substitutions. When ``sym_pos`` is
    ``True``, use Cholesky decomposition.

    Parameters
    ----------
    a : (M, M) array_like
        A square matrix.
    b : (M,) or (M, N) array_like
        Right-hand side matrix in ``a x = b``.
    sym_pos : bool
        Assume a is symmetric and positive definite. If ``True``, use Cholesky
        decomposition.

    Returns
    -------
    x : (M,) or (M, N) Array
        Solution to the system ``a x = b``.  Shape of the return matches the
        shape of `b`.
    T)r   )	_choleskyr   r|   rO   r   )r#   rM   Zsym_posr   ru   r   Zuyr   r   r   solve{  s    r   c             C   s"   t | t| jd | jd d dS )a  
    Compute the inverse of a matrix with LU decomposition and
    forward / backward substitutions.

    Parameters
    ----------
    a : array_like
        Square matrix to be inverted.

    Returns
    -------
    ainv : Array
        Inverse of the matrix `a`.
    r   )r=   )r   r   r   r=   )r#   r   r   r   inv  s    r   c             C   s   dd l }|jj| ddS )Nr   T)r   )r   r!   cholesky)r#   r   r   r   r   _cholesky_lower  s    r   c             C   s   t | \}}|r|S |S dS )a  
    Returns the Cholesky decomposition, :math:`A = L L^*` or
    :math:`A = U^* U` of a Hermitian positive-definite matrix A.

    Parameters
    ----------
    a : (M, M) array_like
        Matrix to be decomposed
    lower : bool, optional
        Whether to compute the upper or lower triangular Cholesky
        factorization.  Default is upper-triangular.

    Returns
    -------
    c : (M, M) Array
        Upper- or lower-triangular Cholesky factor of `a`.
    N)r   )r#   r   r   ru   r   r   r   r     s    r   c             C   s  ddl }| jdkrtd| j\}}||kr4tdtt| jd | jd  dks`d}t|t| jd }t| jd }t| }d| }d	| }	d
| }
i }xt|D ]}xt|D ]}||k rt	j
| jd | | jd | ff||||f< |||f||
||f< q||kr| j||f}|dkrg }xFt|D ]:}|	||||f}t	j|||f|
||ff||< || q>W tj|t|ff}t|f||||f< t	j|||ff||
||f< q| j||f}|dkr,g }xFt|D ]:}|	||||f}t	j|||f|
||ff||< || qW tj|t|ff}t|||f|f||
||f< t	j|
||ff||||f< qW qW tj|
|| gd}tj||| gd}|jt	jddgddgg| jd}t||| j| j|jd}t||
| j| j|jd}||fS )zq
    Private function to perform Cholesky decomposition, which returns both
    lower and upper triangulars.
    r   Nr   z5Dimension must be 2 to perform cholesky decompositionz?Input must be a square matrix to perform cholesky decompositionr   zwAll chunks must be a square matrix to perform cholesky decomposition. Use .rechunk method to change the size of chunks.z	cholesky-zcholesky-lt-dot-zcholesky-upper-)rZ      )r&   )r   r=   r&   )r   rS   rT   r   rQ   re   r=   r   r]   r   r    r@   rO   ra   r)   r   r;   r   r   r   r   r   r!   r   r   r&   r   )r#   r   r   r   r   r   r   rl   r@   Zname_lt_dotZ
name_upperr   r+   rB   r   r   r   r   Zgraph_upperZgraph_lowerZchor   upperr   r   r   r     s`    

 
,


"$r   c             C   s   | d d d    | S )N)sort)r   r   r   r   _sort_decreasing  s    r   c          	   C   sN  t | \}}t||j|}|| | }|d jdd}t| |}d| }|ftjj|j	ddffi}t
j|||gd}	t|	|ddtd}
d	| }|j}|dfttjtjjtj|j	ddf|j	ddfffffi}t
j|||gd}	tjtjd
dgd
dgg| jdtjdd
g|jd\}}}}t|	||jd f|jd |jd}|||
|fS )aA  
    Return the least-squares solution to a linear matrix equation using
    QR decomposition.

    Solves the equation `a x = b` by computing a vector `x` that
    minimizes the Euclidean 2-norm `|| b - a x ||^2`.  The equation may
    be under-, well-, or over- determined (i.e., the number of
    linearly independent rows of `a` can be less than, equal to, or
    greater than its number of linearly independent columns).  If `a`
    is square and of full rank, then `x` (but for round-off error) is
    the "exact" solution of the equation.

    Parameters
    ----------
    a : (M, N) array_like
        "Coefficient" matrix.
    b : (M,) array_like
        Ordinate or "dependent variable" values.

    Returns
    -------
    x : (N,) Array
        Least-squares solution. If `b` is two-dimensional,
        the solutions are in the `K` columns of `x`.
    residuals : (1,) Array
        Sums of residuals; squared Euclidean 2-norm for each column in
        ``b - a*x``.
    rank : Array
        Rank of matrix `a`.
    s : (min(M, N),) Array
        Singular values of `a`.
    r   T)keepdimszlstsq-rank-r   )rZ   r   )r   r=   r&   zlstsq-singular-r   )r&   )r"   r   r|   rO   r;   r   r   r!   Zmatrix_rankr@   r   r   r   r_   r   ZsqrtZeigvalslstsqr   r&   r   )r#   rM   rp   rq   r   Z	residualsrl   ZrnameZrdskro   ZrankZsnameZrtZsdskr4   rs   rv   r   r   r   r     s*    !
$ r   c             C   s  |d krt t| j}nt|tr.t|f}nt |}t|dkrJtd|dkrjd }t|dkrjtd| t	
| jt}|d krt|d j||dd }n|dkrt|dkrtd| jdkrtd	t| d d  j|d
}n|t	jkrZt|}t|dkr |j||d}n6|j|d ddj|d dd}|dkr|j|d}n*|t	j krt|}t|dkr|j||d}n6|j|d ddj|d dd}|dkr|j|d}n|dkrt|dkrtd|dk|jj||d}n~|dkrpt|}t|dkr6|j||d}n6|j|d ddj|d dd}|dkr|j|d}nt|dkr|dkrt|j|d ddj|d dd}|dkr|j|d}nt|dkr
|dkr
| jdkrtd	t| d d  j|d
}nzt|dkrP|dkrP| jdkr6td	t| d d  j|d
}n4t|dkrftdt|| j||dd|  }|S )Nr   z&Improper number of dimensions to norm.Zfror   zInvalid norm order for vectors.)r{   r   g      ?Znucz+SVD based norm not implemented for ndim > 2)r   Tr   F)r{   z Invalid norm order for matrices.r   g      ?)r7   r]   rS   
isinstancer   r_   rQ   rT   Zastyper   Zpromote_typesr&   floatabsr;   r   rP   infrR   Zsqueezer   )r   ordr{   r   rq   r   r   r   normZ  sz    

 
 


 
$
r   )FN)N)r   r   )r   N)r   N)F)F)F)NNF)2Z
__future__r   r   r   r)   	functoolsr   Znumbersr   Znumpyr   rc   baser   r	   Zcompatibilityr
   Zhighlevelgraphr   Zcorer   r   r   Zcreationr   Zrandomr   r   r   r   r$   rb   r   r   r   r   r"   rP   r   r   r   r   r   r   r   r   r   r   r!   r   r   r   r   r   <module>   sL   
  f
\

&
2& 
W

IA
