L iudZddlZddlZddlmZmZmZmZm Z ddl m Z ddl m Z mZmZddlmZddlmZdd lmZdd lmZdd lmZdd lmZdd lmZgdZe ddddZe dddZ e Z!dZ"dZ#e ddddZ$d dZ%e dddddddZ&d dZ'e dddddddZ(d!dZ)y)"zMatrix equation solver routinesN)inv LinAlgErrornormcondsvd)_apply_over_batch)solvesolve_triangularmatrix_balance)get_lapack_funcs)schur)lu)qr)ordqz)_asarray_validated) block_diag)solve_sylvestersolve_continuous_lyapunovsolve_discrete_lyapunovsolve_lyapunovsolve_continuous_aresolve_discrete_are)a)br)qrc\|jdk(s|jdk(rtjtjtjtj d}t d|||f\}tj|j||jSt|d\}}t|jjd\}}tjtj|jj||} t d||| f\} | td| ||| d \} } } | | z} | dkrtd | d tjtj|| |jjS) a Computes a solution (X) to the Sylvester equation :math:`AX + XB = Q`. Parameters ---------- a : (M, M) array_like Leading matrix of the Sylvester equation b : (N, N) array_like Trailing matrix of the Sylvester equation q : (M, N) array_like Right-hand side Returns ------- x : (M, N) ndarray The solution to the Sylvester equation. Raises ------ LinAlgError If solution was not found Notes ----- Computes a solution to the Sylvester matrix equation via the Bartels- Stewart algorithm. The A and B matrices first undergo Schur decompositions. The resulting matrices are used to construct an alternative Sylvester equation (``RY + YS^T = F``) where the R and S matrices are in quasi-triangular form (or, when R, S or F are complex, triangular form). The simplified equation is then solved using ``*TRSYL`` from LAPACK directly. .. versionadded:: 0.11.0 Examples -------- Given `a`, `b`, and `q` solve for `x`: >>> import numpy as np >>> from scipy import linalg >>> a = np.array([[-3, -2, 0], [-1, -1, 3], [3, -5, -1]]) >>> b = np.array([[1]]) >>> q = np.array([[1],[2],[3]]) >>> x = linalg.solve_sylvester(a, b, q) >>> x array([[ 0.0625], [-0.5625], [ 0.6875]]) >>> np.allclose(a.dot(x) + x.dot(b), q) True rsdcztrsylarraysdtyperealoutputzQLAPACK implementation does not contain a proper Sylvester equation solver (TRSYL)Ctranbz!Illegal value encountered in the z term)sizenpfloat32float64 complex64 complex128r emptyshapetypecoderconj transposedot RuntimeErrorr)rrrtdictfuncrur vfr%yscaleinfos [/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/scipy/linalg/_solvers.pyrrsbn vv{affkjjrzzll8 Q1I>xxuT]]';<< 6 "DAq ##%f 5DAq rvvaffh((*A.2Aj1a) 4FE }?@ @1a#.NAud aA ax=teWEJKK 66"&&A, 2 2 4 55cvtjt|d}tjt|d}t}t ||fD]N\}}tj |rt }tj|jr>tdd|d|j|jk7r td|jdk(r~tjtjtjtjd}td ||f \}tj |j||j" St%|d \}}|j'j(j+|j+|} td|| f} |turdnd} | ||| | \} } }|dkrtd| d|dk(rt-j.dt0d| | z} |j+| j+|j'j(S)a Solves the continuous Lyapunov equation :math:`AX + XA^H = Q`. Uses the Bartels-Stewart algorithm to find :math:`X`. Parameters ---------- a : array_like A square matrix q : array_like Right-hand side square matrix Returns ------- x : ndarray Solution to the continuous Lyapunov equation See Also -------- solve_discrete_lyapunov : computes the solution to the discrete-time Lyapunov equation solve_sylvester : computes the solution to the Sylvester equation Notes ----- The continuous Lyapunov equation is a special form of the Sylvester equation, hence this solver relies on LAPACK routine ?TRSYL. .. versionadded:: 0.11.0 Examples -------- Given `a` and `q` solve for `x`: >>> import numpy as np >>> from scipy import linalg >>> a = np.array([[-3, -2, 0], [-1, -1, 0], [0, -5, -1]]) >>> b = np.array([2, 4, -1]) >>> q = np.eye(3) >>> x = linalg.solve_continuous_lyapunov(a, q) >>> x array([[ -0.75 , 0.875 , -3.75 ], [ 0.875 , -1.375 , 5.3125], [ -3.75 , 5.3125, -27.0625]]) >>> np.allclose(a.dot(x) + x.dot(a.T), q) True T check_finiteMatrix aq should be square.*Matrix a and q should have the same shape.rrr$r&r(r*r+r%Tr-r.zH?TRSYL exited with the internal error "illegal value in argument number z8.". See LAPACK documentation for the ?TRSYL error codes.r zInput "a" has an eigenvalue pair whose sum is very close to or exactly zero. The solution is obtained via perturbing the coefficients.r) stacklevel)r1 atleast_2drfloat enumerate iscomplexobjcomplexequalr7 ValueErrorr0r2r3r4r5r r6r8rr9rOr;warningswarnRuntimeWarning)rrr_or_cind_r=r>r?r@rBr% dtype_stringrCrDrEs rFrrtsf (>?A (>?A FQF#FQ ??1 Fxx!wtCyk1CDE E F ww!''EFF vv{jjrzzll8 QF;xxuT]]';<< 6 "DAq  quuQx A Wq!f -E E/3sL1a,7NAud ax>?CeWELLM M  B% 4JA 558<< ##rGctj||j}tj|jd|z }t ||j }tj||jS)z Solves the discrete Lyapunov equation directly. This function is called by the `solve_discrete_lyapunov` function with `method=direct`. It is not supposed to be called directly. r)r1kronr9eyer7r flattenreshape)rrlhsxs rF_solve_discrete_lyapunov_directrfs\ ''!QVVX C &&1  $C c199;A ::a !!rGc tj|jd}|jj }t ||z}tj ||z |}dtj tj t ||z||z}t|jj | S)z Solves the discrete Lyapunov equation using a bilinear transformation. This function is called by the `solve_discrete_lyapunov` function with `method=bilinear`. It is not supposed to be called directly. rr)r1rar7r9r:rr;r)rrraaHaHI_invrr"s rF!_solve_discrete_lyapunov_bilinearrjs && C    B"s(mG rCx!A "&&AG a(' 22A !&&(,,. 33rGctj|}tj|}||jddk\rd}nd}|j}|dk(rt ||}|S|dk(rt ||}|St d|)a Solves the discrete Lyapunov equation :math:`AXA^H - X + Q = 0`. Parameters ---------- a, q : (M, M) array_like Square matrices corresponding to A and Q in the equation above respectively. Must have the same shape. method : {'direct', 'bilinear'}, optional Type of solver. If not given, chosen to be ``direct`` if ``M`` is less than 10 and ``bilinear`` otherwise. Returns ------- x : ndarray Solution to the discrete Lyapunov equation See Also -------- solve_continuous_lyapunov : computes the solution to the continuous-time Lyapunov equation Notes ----- This section describes the available solvers that can be selected by the 'method' parameter. The default method is *direct* if ``M`` is less than 10 and ``bilinear`` otherwise. Method *direct* uses a direct analytical solution to the discrete Lyapunov equation. The algorithm is given in, for example, [1]_. However, it requires the linear solution of a system with dimension :math:`M^2` so that performance degrades rapidly for even moderately sized matrices. Method *bilinear* uses a bilinear transformation to convert the discrete Lyapunov equation to a continuous Lyapunov equation :math:`(BX+XB'=-C)` where :math:`B=(A-I)(A+I)^{-1}` and :math:`C=2(A' + I)^{-1} Q (A + I)^{-1}`. The continuous equation can be efficiently solved since it is a special case of a Sylvester equation. The transformation algorithm is from Popov (1964) as described in [2]_. .. versionadded:: 0.11.0 References ---------- .. [1] "Lyapunov equation", Wikipedia, https://en.wikipedia.org/wiki/Lyapunov_equation#Discrete_time .. [2] Gajic, Z., and M.T.J. Qureshi. 2008. Lyapunov Matrix Equation in System Stability and Control. Dover Books on Engineering Series. Dover Publications. Examples -------- Given `a` and `q` solve for `x`: >>> import numpy as np >>> from scipy import linalg >>> a = np.array([[0.2, 0.5],[0.7, -0.9]]) >>> q = np.eye(2) >>> x = linalg.solve_discrete_lyapunov(a, q) >>> x array([[ 0.70872893, 1.43518822], [ 1.43518822, -2.4266315 ]]) >>> np.allclose(a.dot(x).dot(a.T)-x, -q) True r bilineardirectzUnknown solver )r1asarrayr7lowerrfrjrW)rrmethodmethres rFrrsN 1 A 1 A ~ 771: FF <<>D x +Aq 1 H   -a 3 H?6(344rGc $t|||||||S)aZ Solves the continuous-time algebraic Riccati equation (CARE). The CARE is defined as .. math:: X A + A^H X - X B R^{-1} B^H X + Q = 0 The limitations for a solution to exist are : * All eigenvalues of :math:`A` on the right half plane, should be controllable. * The associated hamiltonian pencil (See Notes), should have eigenvalues sufficiently away from the imaginary axis. Moreover, if ``e`` or ``s`` is not precisely ``None``, then the generalized version of CARE .. math:: E^HXA + A^HXE - (E^HXB + S) R^{-1} (B^HXE + S^H) + Q = 0 is solved. When omitted, ``e`` is assumed to be the identity and ``s`` is assumed to be the zero matrix with sizes compatible with ``a`` and ``b``, respectively. 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. Parameters ---------- a : (M, M) array_like Square matrix b : (M, N) array_like Input q : (M, M) array_like Input r : (N, N) array_like Nonsingular square matrix e : (M, M) array_like, optional Nonsingular square matrix s : (M, N) array_like, optional Input balanced : bool, optional The boolean that indicates whether a balancing step is performed on the data. The default is set to True. Returns ------- x : (M, M) ndarray Solution to the continuous-time algebraic Riccati equation. Raises ------ LinAlgError For cases where the stable subspace of the pencil could not be isolated. See Notes section and the references for details. See Also -------- solve_discrete_are : Solves the discrete-time algebraic Riccati equation Notes ----- The equation is solved by forming the extended hamiltonian matrix pencil, as described in [1]_, :math:`H - \lambda J` given by the block matrices :: [ A 0 B ] [ E 0 0 ] [-Q -A^H -S ] - \lambda * [ 0 E^H 0 ] [ S^H B^H R ] [ 0 0 0 ] and using a QZ decomposition method. In this algorithm, the fail conditions are linked to the symmetry of the product :math:`U_2 U_1^{-1}` and condition number of :math:`U_1`. Here, :math:`U` is the 2m-by-m matrix that holds the eigenvectors spanning the stable subspace with 2-m rows and partitioned into two m-row matrices. See [1]_ and [2]_ for more details. In order to improve the QZ decomposition accuracy, the pencil goes through a balancing step where the sum of absolute values of :math:`H` and :math:`J` entries (after removing the diagonal entries of the sum) is balanced following the recipe given in [3]_. .. versionadded:: 0.11.0 References ---------- .. [1] P. van Dooren , "A Generalized Eigenvalue Approach For Solving Riccati Equations.", SIAM Journal on Scientific and Statistical Computing, Vol.2(2), :doi:`10.1137/0902010` .. [2] A.J. Laub, "A Schur Method for Solving Algebraic Riccati Equations.", Massachusetts Institute of Technology. Laboratory for Information and Decision Systems. LIDS-R ; 859. Available online : http://hdl.handle.net/1721.1/1301 .. [3] P. Benner, "Symplectic Balancing of Hamiltonian Matrices", 2001, SIAM J. Sci. Comput., 2001, Vol.22(5), :doi:`10.1137/S1064827500367993` Examples -------- Given `a`, `b`, `q`, and `r` solve for `x`: >>> import numpy as np >>> from scipy import linalg >>> a = np.array([[4, 3], [-4.5, -3.5]]) >>> b = np.array([[1], [-1]]) >>> q = np.array([[9, 6], [6, 4.]]) >>> r = 1 >>> x = linalg.solve_continuous_are(a, b, q, r) >>> x array([[ 21.72792206, 14.48528137], [ 14.48528137, 9.65685425]]) >>> np.allclose(a.T.dot(x) + x.dot(a)-x.dot(b).dot(b.T).dot(x), -q) True )_solve_continuous_arerrrr?er balanceds rFrrVsx !Aq!Q8 < 8C{{3 S 12''#,C#a!*s2Aw.12AruuQC!I-..Cag,s);;K  A  A aA23i=DAq !QR% a4AaC4j)A $1Q3$(   4AaC4!A#:/A%fYGQ4)-E$+-Aq!Q1  }"))QUU1RaR!V9-qRaRy9:;1 BQBF)C ABF)CCJBBbzBJJrN"=>> )"'')++*-((*,,046(,    46!!CC $4   S!T]S!W $$ HHJLL  S !E5!nG EJJLNN "EFFBJJu-s7{;>> import numpy as np >>> from scipy import linalg as la >>> a = np.array([[0, 1], [0, -1]]) >>> b = np.array([[1, 0], [2, 1]]) >>> q = np.array([[-4, -4], [-4, 7]]) >>> r = np.array([[9, 3], [3, 1]]) >>> x = la.solve_discrete_are(a, b, q, r) >>> x array([[-4., -4.], [-4., 7.]]) >>> R = la.solve(r + b.T.dot(x).dot(b), b.T.dot(x).dot(a)) >>> np.allclose(a.T.dot(x).dot(a) - x - a.T.dot(x).dot(b).dot(R), -q) True )_solve_discrete_arerus rFrr-s| q!Q1a ::rGc  t||||||d\ }}}}}}}}} } tjd|z|zd|z|zf| } || d|d|f<|| d|d|zdf<| | |d|zd|f<|tj|n|j j | |d|z|d|zf<|dn| | |d|zd|zdf<|dn|j j | d|zdd|f<|| d|zdd|zdf<tj | | } |tj|n|| d|d|f<|j j | |d|z|d|zf<|j j | d|zd|d|zf<|rtj| tj| z} tj| dt| dd\}\}}tj|tj|stj|}tj||d|z|d|z dz }dtj|| |d|zdfz}|dddftj|z}| |z} | |z} t!| dd| df\}}|dd|dfj j j#| dddd|zf} |dd|dfj j j#| dddd|zf} | t$urdnd }t'| | d d d d | \}}}}}}|Dt!tj(|j#|d|d|f||dd|ff\}}|d|d|f}||dd|f}t+|\}}}dt-|z tj.dkr t1dt3|j j t3|j j |j j d d j j j#|j j }|r|d|df|d|zz}|j j j#|}t5|d}||j j z }tj6tj.dd|zg}t5|d|kDr t1d||j j zdz S)Ndarerr(rzr rr{r*rUiucTFrrrrrrrzMThe associated symplectic pencil has eigenvalues too close to the unit circle)rr1zerosrar9rOrrrr rrrrrrrr;rRrrrrrrr rr)rrrr?rvr rwrrr[rrrrr]rrq_of_qrrr@rrrrrrerrrs rFrrs./A561aAv/O+Aq!Q1aFG !A#a%1Qv.AAbqb"1"fIAbqb!A#$hK2Aa!eRaRiL#$9bffQi!&&(**Aa!eQqsUlO9R1"Aa!eQqSTkN "qvvxzzAacdBQBhKAacdAaCDjM av&AYq AAbqb"1"fIffhjjAa!eQqsUlOffhjj[AacdAacEkN FF1Iq ! B$QA> 8C{{3 S 12''#,C#a!*s2Aw.12AruuQC!I-..Cag,s);;K  A  AAa!fIJGQ12##Aa!A#gJ/A12##Aa!A#gJ/A%fYGQ)-)-*/$+ -Aq!Q1 }"))QUU1RaR!V9-qRaRy9:;1 BQBF)C ABF)CCJBBbzBJJrN"=>> )"'')++*-((*,,046(,    46!!CC $4   S!T]S!W $$ HHJLL  S !E5!nG EJJLNN "EFFBJJu-s7{;tdd|d|j\} } | |jdk7r td | |jdk7r td | |jdk7r td t||fD]a\}} t| | jjz d tjt| d d zkDsQtdd|d|dk(rEt|dd} | dk(s%| tjdt|d zkr td|duxs|du} | r'|tjt |d}tj|js td| |jdk7r tdt|dd} | dk(s%| tjdt|d zkr tdtj |rt }|_tjt |d}|j|jk7r tdtj |rt }||||||| | || f S)a A helper function to validate the arguments supplied to the Riccati equation solvers. Any discrepancy found in the input matrices leads to a ``ValueError`` exception. Essentially, it performs: - a check whether the input is free of NaN and Infs - a pass for the data through ``numpy.atleast_2d()`` - squareness check of the relevant arrays - shape consistency check of the arrays - singularity check of the relevant arrays - symmetricity check of the relevant matrices - a check whether the regular or the generalized version is asked. This function is used by ``solve_continuous_are`` and ``solve_discrete_are``. Parameters ---------- a, b, q, r, e, s : array_like Input data eq_type : str Accepted arguments are 'care' and 'dare'. Returns ------- a, b, q, r, e, s : ndarray Regularized input data m, n : int shape of the problem r_or_c : type Data type of the problem, returns float or complex gen_or_not : bool Type of the equation, True for generalized and False for regular ARE. )rryz;Equation type unknown. Only 'care' and 'dare' is understoodTrIrKaqrrMrz3Matrix a and b should have the same number of rows.rNz3Matrix b and r should have the same number of cols.r drz should be symmetric/hermitian.ryF) compute_uvrzrz!Matrix r is numerically singular.NzMatrix e should be square.z*Matrix a and e should have the same shape.z!Matrix e is numerically singular.z*Matrix b and s should have the same shape.)rprWr1rQrrTrUrRrSrVr7rr9rOrr)rrrr?rvr eq_typer[r\matrrmin_svgeneralized_cases rFrrs#N}}..@A A (>?A (>?A (>?A (>?A*WFq!Qi(GS ??3 Fxx#wuSzl2DEF F G 77DAqAGGAJNOOAGGAJEFFAGGAJNOOq!f%SS chhjll"A &DaL)A#)E EwtCyk1PQR RS &Q5)"- R<6BJJrN41:$==@A A}5  = 0FGA88QWW% !=>>AGGAJ !MNNu-b1F|v 2a(CC !DEEq!  = 0FGAww!''! !MNNq!  aAq!Q6+; ;;rG)N)NNT)ry)*__doc__rXnumpyr1 numpy.linalgrrrrrscipy._lib._utilr_basicr r r lapackr _decomp_schurr _decomp_lur _decomp_qrr _decomp_qzr_decompr_special_matricesr__all__rrrrfrjrrrtrrrrGrFrs %::.;;$ ') 9 8Xx0Q61Q6h8X&`$'`$H+ " 48X&X 'X v|=~8Xx8XNTOTn~;B8Xx8XNVOVrh