L i%|ddlmZddlZddlmZmZddlmZm Z ddl m Z m Z dgZ ddZed d d d d Zy))IterableN)_asarray_validated_apply_over_batch) block_diag LinAlgError)_compute_lworkget_lapack_funcscossinc |s|r|dn t|}|dn t|}t|d}tj|jddst d|jdd|jd}||k\s|dkrt d|d |jdd ||k\s|dkrt d |d |jdd |d d|d|f|d d||df|d |dd|f|d |d|dff\}} } } nNt |ts t dt|dk7rt dt|d|D\}} } } t|| | | ||||S)u Compute the cosine-sine (CS) decomposition of an orthogonal/unitary matrix. X is an ``(m, m)`` orthogonal/unitary matrix, partitioned as the following where upper left block has the shape of ``(p, q)``:: ┌ ┐ │ I 0 0 │ 0 0 0 │ ┌ ┐ ┌ ┐│ 0 C 0 │ 0 -S 0 │┌ ┐* │ X11 │ X12 │ │ U1 │ ││ 0 0 0 │ 0 0 -I ││ V1 │ │ │ ────┼──── │ = │────┼────││─────────┼─────────││────┼────│ │ X21 │ X22 │ │ │ U2 ││ 0 0 0 │ I 0 0 ││ │ V2 │ └ ┘ └ ┘│ 0 S 0 │ 0 C 0 │└ ┘ │ 0 0 I │ 0 0 0 │ └ ┘ ``U1``, ``U2``, ``V1``, ``V2`` are square orthogonal/unitary matrices of dimensions ``(p,p)``, ``(m-p,m-p)``, ``(q,q)``, and ``(m-q,m-q)`` respectively, and ``C`` and ``S`` are ``(r, r)`` nonnegative diagonal matrices satisfying ``C^2 + S^2 = I`` where ``r = min(p, m-p, q, m-q)``. Moreover, the rank of the identity matrices are ``min(p, q) - r``, ``min(p, m - q) - r``, ``min(m - p, q) - r``, and ``min(m - p, m - q) - r`` respectively. X can be supplied either by itself and block specifications p, q or its subblocks in an iterable from which the shapes would be derived. See the examples below. Parameters ---------- X : array_like, iterable complex unitary or real orthogonal matrix to be decomposed, or iterable of subblocks ``X11``, ``X12``, ``X21``, ``X22``, when ``p``, ``q`` are omitted. p : int, optional Number of rows of the upper left block ``X11``, used only when X is given as an array. q : int, optional Number of columns of the upper left block ``X11``, used only when X is given as an array. separate : bool, optional if ``True``, the low level components are returned instead of the matrix factors, i.e. ``(u1,u2)``, ``theta``, ``(v1h,v2h)`` instead of ``u``, ``cs``, ``vh``. swap_sign : bool, optional if ``True``, the ``-S``, ``-I`` block will be the bottom left, otherwise (by default) they will be in the upper right block. compute_u : bool, optional if ``False``, ``u`` won't be computed and an empty array is returned. compute_vh : bool, optional if ``False``, ``vh`` won't be computed and an empty array is returned. Returns ------- u : ndarray When ``compute_u=True``, contains the block diagonal orthogonal/unitary matrix consisting of the blocks ``U1`` (``p`` x ``p``) and ``U2`` (``m-p`` x ``m-p``) orthogonal/unitary matrices. If ``separate=True``, this contains the tuple of ``(U1, U2)``. cs : ndarray The cosine-sine factor with the structure described above. If ``separate=True``, this contains the ``theta`` array containing the angles in radians. vh : ndarray When ``compute_vh=True`, contains the block diagonal orthogonal/unitary matrix consisting of the blocks ``V1H`` (``q`` x ``q``) and ``V2H`` (``m-q`` x ``m-q``) orthogonal/unitary matrices. If ``separate=True``, this contains the tuple of ``(V1H, V2H)``. Notes ----- The documentation is written assuming array arguments are of specified "core" shapes. However, array argument(s) of this function may have additional "batch" dimensions prepended to the core shape. In this case, the array is treated as a batch of lower-dimensional slices; see :ref:`linalg_batch` for details. References ---------- .. [1] Brian D. Sutton. Computing the complete CS decomposition. Numer. Algorithms, 50(1):33-65, 2009. Examples -------- >>> import numpy as np >>> from scipy.linalg import cossin >>> from scipy.stats import unitary_group >>> x = unitary_group.rvs(4) >>> u, cs, vdh = cossin(x, p=2, q=2) >>> np.allclose(x, u @ cs @ vdh) True Same can be entered via subblocks without the need of ``p`` and ``q``. Also let's skip the computation of ``u`` >>> ue, cs, vdh = cossin((x[:2, :2], x[:2, 2:], x[2:, :2], x[2:, 2:]), ... compute_u=False) >>> print(ue) [] >>> np.allclose(x, u @ cs @ vdh) True NrT) check_finitez=Cosine Sine decomposition only supports square matrices, got rz invalid p=z, 0zcossin..s:1bmmA.:s!)separate swap_sign compute_u compute_vh) intrrequalshape ValueError isinstancerlen_cossin) Xpqrrrrmx11x12x21x22s rr r sT AAAAA qt 4xx&//0wwrs|n>? ? GGBK 6Q!Vz!F1772;-zJK K 6Q!Vz!F1772;-zJK KRaR! naRaR nQR! naQR n>S#s 8 $:; ; q6Q;558VH>? ?::S#s 3S#I&: ??)r&)r'r+)r(r+)r)r+c6tgd||||gD]%\}} | jddk(st|d|j\} } |j\} } |j| | fk7rtd| | fd|j|j| | fk7rtd| | fd|j| | z| | zk7rtd| | zd | | zd | | z}t||||fDcgc]}t j |c}}|rd nd }t ||d zg||||g\}}t||| | }|r |d|ddnd|i}|d||||||||d|d |^}}}}}}}|j|z}|dkrtd| d||dkDrt|d||r ||f|||ffSt||}t||}t jt j|} t jt j|}!t| | || z || z }"t| | |"z }#t| || z |"z }$t|| z | |"z }%t|| z || z |"z }&t jt j |#|$|%|&|"g|j"}'t j$||f|j"}(|'d|#d|#f|(d|#d|#f<|#|"z})|#|"z|$z}*|#|%z|&zd|"zz}+|#|%z|&zd|"zz|$z},|r |'d|$d|$fn |'d|$d|$f |(|)|*|+|,f<| |&z|"z})| |&z|"z|%z}*|#|"z}+|#|"z|%z},|r |'d|%d|%f n |'d|%d|%f|(|)|*|+|,f<|'d|&d|&f|(| | |&z| | |&zf<| |(|#|#|"z|#|#|"zf<| |(| |&z| |&z|"z|#|"z|%z|&zd|"z|#z|%z|&zf<|#})|#|"z}*|#|%z|&z|"z}+|#|%z|&zd|"zz},|r|!n|! |(|)|*|+|,f<|r|! n|!|(| |&z| |&z|"z|#|#|"zf<||(|fScc}w)N)r&r'r(r)rrz can't be emptyz Invalid x12 dimensions: desired z, got z Invalid x21 dimensions: desired zWThe subblocks have compatible sizes but don't form a square array (instead they form a rz5 array). This might be due to missing p, q arguments.uncsdorcsd_lwork)r%r#r$)lworklrworkr0F) r&r'r(r) compute_u1 compute_u2 compute_v1t compute_v2ttranssignszillegal value in argument z of internal z did not converge: )dtyper+)ziprranyr iscomplexobjr r typecoderrdiagcossinmineyemaxr8zeros)-r&r'r(r)rrrrnameblockr#r$mmpmmqr%rcplxdrivercsd csd_lworkr0 lwork_args_thetau1u2v1hv2hinfo method_nameUVDHcsrn11n12n21n22IdCSxsxeysyes- rr!r!s7c3/17 e ;;q>Q v_56 67 99DAqyyHC yyQH;QH:F # {,- - yyS!H;S!H:F # {,- - 3w!c'#gYaCy1;;< < CA S#sC,@Aq"A BDW'F%vv/@&A'*Cc&:rksL$B04 *(-7;C?L:z:zBZCZr*