4444
4545from .exception import ControlSlycot , ControlArgument , ControlDimension , \
4646 slycot_check
47- from .statesp import _ssmatrix
4847
4948# Make sure we have access to the right slycot routines
5049try :
@@ -151,12 +150,12 @@ def lyap(A, Q, C=None, E=None, method=None):
151150 m = Q .shape [0 ]
152151
153152 # Check to make sure input matrices are the right shape and type
154- _check_shape ("A" , A , n , n , square = True )
153+ _check_shape (A , n , n , square = True , name = "A" )
155154
156155 # Solve standard Lyapunov equation
157156 if C is None and E is None :
158157 # Check to make sure input matrices are the right shape and type
159- _check_shape ("Q" , Q , n , n , square = True , symmetric = True )
158+ _check_shape (Q , n , n , square = True , symmetric = True , name = "Q" )
160159
161160 if method == 'scipy' :
162161 # Solve the Lyapunov equation using SciPy
@@ -171,8 +170,8 @@ def lyap(A, Q, C=None, E=None, method=None):
171170 # Solve the Sylvester equation
172171 elif C is not None and E is None :
173172 # Check to make sure input matrices are the right shape and type
174- _check_shape ("Q" , Q , m , m , square = True )
175- _check_shape ("C" , C , n , m )
173+ _check_shape (Q , m , m , square = True , name = "Q" )
174+ _check_shape (C , n , m , name = "C" )
176175
177176 if method == 'scipy' :
178177 # Solve the Sylvester equation using SciPy
@@ -184,8 +183,8 @@ def lyap(A, Q, C=None, E=None, method=None):
184183 # Solve the generalized Lyapunov equation
185184 elif C is None and E is not None :
186185 # Check to make sure input matrices are the right shape and type
187- _check_shape ("Q" , Q , n , n , square = True , symmetric = True )
188- _check_shape ("E" , E , n , n , square = True )
186+ _check_shape (Q , n , n , square = True , symmetric = True , name = "Q" )
187+ _check_shape (E , n , n , square = True , name = "E" )
189188
190189 if method == 'scipy' :
191190 raise ControlArgument (
@@ -210,7 +209,7 @@ def lyap(A, Q, C=None, E=None, method=None):
210209 else :
211210 raise ControlArgument ("Invalid set of input parameters" )
212211
213- return _ssmatrix ( X )
212+ return X
214213
215214
216215def dlyap (A , Q , C = None , E = None , method = None ):
@@ -281,12 +280,12 @@ def dlyap(A, Q, C=None, E=None, method=None):
281280 m = Q .shape [0 ]
282281
283282 # Check to make sure input matrices are the right shape and type
284- _check_shape ("A" , A , n , n , square = True )
283+ _check_shape (A , n , n , square = True , name = "A" )
285284
286285 # Solve standard Lyapunov equation
287286 if C is None and E is None :
288287 # Check to make sure input matrices are the right shape and type
289- _check_shape ("Q" , Q , n , n , square = True , symmetric = True )
288+ _check_shape (Q , n , n , square = True , symmetric = True , name = "Q" )
290289
291290 if method == 'scipy' :
292291 # Solve the Lyapunov equation using SciPy
@@ -301,8 +300,8 @@ def dlyap(A, Q, C=None, E=None, method=None):
301300 # Solve the Sylvester equation
302301 elif C is not None and E is None :
303302 # Check to make sure input matrices are the right shape and type
304- _check_shape ("Q" , Q , m , m , square = True )
305- _check_shape ("C" , C , n , m )
303+ _check_shape (Q , m , m , square = True , name = "Q" )
304+ _check_shape (C , n , m , name = "C" )
306305
307306 if method == 'scipy' :
308307 raise ControlArgument (
@@ -314,8 +313,8 @@ def dlyap(A, Q, C=None, E=None, method=None):
314313 # Solve the generalized Lyapunov equation
315314 elif C is None and E is not None :
316315 # Check to make sure input matrices are the right shape and type
317- _check_shape ("Q" , Q , n , n , square = True , symmetric = True )
318- _check_shape ("E" , E , n , n , square = True )
316+ _check_shape (Q , n , n , square = True , symmetric = True , name = "Q" )
317+ _check_shape (E , n , n , square = True , name = "E" )
319318
320319 if method == 'scipy' :
321320 raise ControlArgument (
@@ -333,7 +332,7 @@ def dlyap(A, Q, C=None, E=None, method=None):
333332 else :
334333 raise ControlArgument ("Invalid set of input parameters" )
335334
336- return _ssmatrix ( X )
335+ return X
337336
338337
339338#
@@ -407,10 +406,10 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
407406 m = B .shape [1 ]
408407
409408 # Check to make sure input matrices are the right shape and type
410- _check_shape (_As , A , n , n , square = True )
411- _check_shape (_Bs , B , n , m )
412- _check_shape (_Qs , Q , n , n , square = True , symmetric = True )
413- _check_shape (_Rs , R , m , m , square = True , symmetric = True )
409+ _check_shape (A , n , n , square = True , name = _As )
410+ _check_shape (B , n , m , name = _Bs )
411+ _check_shape (Q , n , n , square = True , symmetric = True , name = _Qs )
412+ _check_shape (R , m , m , square = True , symmetric = True , name = _Rs )
414413
415414 # Solve the standard algebraic Riccati equation
416415 if S is None and E is None :
@@ -423,7 +422,7 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
423422 X = sp .linalg .solve_continuous_are (A , B , Q , R )
424423 K = np .linalg .solve (R , B .T @ X )
425424 E , _ = np .linalg .eig (A - B @ K )
426- return _ssmatrix ( X ) , E , _ssmatrix ( K )
425+ return X , E , K
427426
428427 # Make sure we can import required slycot routines
429428 try :
@@ -448,7 +447,7 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
448447
449448 # Return the solution X, the closed-loop eigenvalues L and
450449 # the gain matrix G
451- return _ssmatrix ( X ) , w [:n ], _ssmatrix ( G )
450+ return X , w [:n ], G
452451
453452 # Solve the generalized algebraic Riccati equation
454453 else :
@@ -457,8 +456,8 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
457456 E = np .eye (A .shape [0 ]) if E is None else np .array (E , ndmin = 2 )
458457
459458 # Check to make sure input matrices are the right shape and type
460- _check_shape (_Es , E , n , n , square = True )
461- _check_shape (_Ss , S , n , m )
459+ _check_shape (E , n , n , square = True , name = _Es )
460+ _check_shape (S , n , m , name = _Ss )
462461
463462 # See if we should solve this using SciPy
464463 if method == 'scipy' :
@@ -469,7 +468,7 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
469468 X = sp .linalg .solve_continuous_are (A , B , Q , R , s = S , e = E )
470469 K = np .linalg .solve (R , B .T @ X @ E + S .T )
471470 eigs , _ = sp .linalg .eig (A - B @ K , E )
472- return _ssmatrix ( X ) , eigs , _ssmatrix ( K )
471+ return X , eigs , K
473472
474473 # Make sure we can find the required slycot routine
475474 try :
@@ -494,7 +493,7 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
494493
495494 # Return the solution X, the closed-loop eigenvalues L and
496495 # the gain matrix G
497- return _ssmatrix ( X ) , L , _ssmatrix ( G )
496+ return X , L , G
498497
499498def dare (A , B , Q , R , S = None , E = None , stabilizing = True , method = None ,
500499 _As = "A" , _Bs = "B" , _Qs = "Q" , _Rs = "R" , _Ss = "S" , _Es = "E" ):
@@ -564,14 +563,14 @@ def dare(A, B, Q, R, S=None, E=None, stabilizing=True, method=None,
564563 m = B .shape [1 ]
565564
566565 # Check to make sure input matrices are the right shape and type
567- _check_shape (_As , A , n , n , square = True )
568- _check_shape (_Bs , B , n , m )
569- _check_shape (_Qs , Q , n , n , square = True , symmetric = True )
570- _check_shape (_Rs , R , m , m , square = True , symmetric = True )
566+ _check_shape (A , n , n , square = True , name = _As )
567+ _check_shape (B , n , m , name = _Bs )
568+ _check_shape (Q , n , n , square = True , symmetric = True , name = _Qs )
569+ _check_shape (R , m , m , square = True , symmetric = True , name = _Rs )
571570 if E is not None :
572- _check_shape (_Es , E , n , n , square = True )
571+ _check_shape (E , n , n , square = True , name = _Es )
573572 if S is not None :
574- _check_shape (_Ss , S , n , m )
573+ _check_shape (S , n , m , name = _Ss )
575574
576575 # Figure out how to solve the problem
577576 if method == 'scipy' :
@@ -589,7 +588,7 @@ def dare(A, B, Q, R, S=None, E=None, stabilizing=True, method=None,
589588 else :
590589 L , _ = sp .linalg .eig (A - B @ G , E )
591590
592- return _ssmatrix ( X ) , L , _ssmatrix ( G )
591+ return X , L , G
593592
594593 # Make sure we can import required slycot routine
595594 try :
@@ -618,7 +617,7 @@ def dare(A, B, Q, R, S=None, E=None, stabilizing=True, method=None,
618617
619618 # Return the solution X, the closed-loop eigenvalues L and
620619 # the gain matrix G
621- return _ssmatrix ( X ) , L , _ssmatrix ( G )
620+ return X , L , G
622621
623622
624623# Utility function to decide on method to use
@@ -632,15 +631,17 @@ def _slycot_or_scipy(method):
632631
633632
634633# Utility function to check matrix dimensions
635- def _check_shape (name , M , n , m , square = False , symmetric = False ):
634+ def _check_shape (M , n , m , square = False , symmetric = False , name = "??" ):
636635 if square and M .shape [0 ] != M .shape [1 ]:
637636 raise ControlDimension ("%s must be a square matrix" % name )
638637
639638 if symmetric and not _is_symmetric (M ):
640639 raise ControlArgument ("%s must be a symmetric matrix" % name )
641640
642641 if M .shape [0 ] != n or M .shape [1 ] != m :
643- raise ControlDimension ("Incompatible dimensions of %s matrix" % name )
642+ raise ControlDimension (
643+ f"Incompatible dimensions of { name } matrix; "
644+ f"expected ({ n } , { m } ) but found { M .shape } " )
644645
645646
646647# Utility function to check if a matrix is symmetric
0 commit comments