3
3
# Implementation of the functions lyap, dlyap, care and dare
4
4
# for solution of Lyapunov and Riccati equations.
5
5
#
6
- # Author : Bjorn Olofsson
6
+ # Original author : Bjorn Olofsson
7
7
8
8
# Copyright (c) 2011, All rights reserved.
9
9
@@ -162,6 +162,7 @@ def lyap(A, Q, C=None, E=None, method=None):
162
162
_check_shape ("Q" , Q , n , n , square = True , symmetric = True )
163
163
164
164
if method == 'scipy' :
165
+ # Solve the Lyapunov equation using SciPy
165
166
return sp .linalg .solve_continuous_lyapunov (A , - Q )
166
167
167
168
# Solve the Lyapunov equation by calling Slycot function sb03md
@@ -177,6 +178,7 @@ def lyap(A, Q, C=None, E=None, method=None):
177
178
_check_shape ("C" , C , n , m )
178
179
179
180
if method == 'scipy' :
181
+ # Solve the Sylvester equation using SciPy
180
182
return sp .linalg .solve_sylvester (A , Q , - C )
181
183
182
184
# Solve the Sylvester equation by calling the Slycot function sb04md
@@ -293,6 +295,7 @@ def dlyap(A, Q, C=None, E=None, method=None):
293
295
_check_shape ("Q" , Q , n , n , square = True , symmetric = True )
294
296
295
297
if method == 'scipy' :
298
+ # Solve the Lyapunov equation using SciPy
296
299
return sp .linalg .solve_discrete_lyapunov (A , Q )
297
300
298
301
# Solve the Lyapunov equation by calling the Slycot function sb03md
@@ -396,24 +399,6 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
396
399
# Decide what method to use
397
400
method = _slycot_or_scipy (method )
398
401
399
- if method == 'slycot' :
400
- # Make sure we can import required slycot routines
401
- try :
402
- from slycot import sb02md
403
- except ImportError :
404
- raise ControlSlycot ("Can't find slycot module 'sb02md'" )
405
-
406
- try :
407
- from slycot import sb02mt
408
- except ImportError :
409
- raise ControlSlycot ("Can't find slycot module 'sb02mt'" )
410
-
411
- # Make sure we can find the required slycot routine
412
- try :
413
- from slycot import sg02ad
414
- except ImportError :
415
- raise ControlSlycot ("Can't find slycot module 'sg02ad'" )
416
-
417
402
# Reshape input arrays
418
403
A = np .array (A , ndmin = 2 )
419
404
B = np .array (B , ndmin = 2 )
@@ -447,9 +432,16 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
447
432
E , _ = np .linalg .eig (A - B @ K )
448
433
return _ssmatrix (X ), E , _ssmatrix (K )
449
434
450
- # Create back-up of arrays needed for later computations
451
- R_ba = copy (R )
452
- B_ba = copy (B )
435
+ # Make sure we can import required slycot routines
436
+ try :
437
+ from slycot import sb02md
438
+ except ImportError :
439
+ raise ControlSlycot ("Can't find slycot module 'sb02md'" )
440
+
441
+ try :
442
+ from slycot import sb02mt
443
+ except ImportError :
444
+ raise ControlSlycot ("Can't find slycot module 'sb02mt'" )
453
445
454
446
# Solve the standard algebraic Riccati equation by calling Slycot
455
447
# functions sb02mt and sb02md
@@ -459,7 +451,7 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
459
451
X , rcond , w , S_o , U , A_inv = sb02md (n , A , G , Q , 'C' , sort = sort )
460
452
461
453
# Calculate the gain matrix G
462
- G = solve (R_ba , B_ba .T ) @ X
454
+ G = solve (R , B .T ) @ X
463
455
464
456
# Return the solution X, the closed-loop eigenvalues L and
465
457
# the gain matrix G
@@ -486,11 +478,11 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
486
478
eigs , _ = sp .linalg .eig (A - B @ K , E )
487
479
return _ssmatrix (X ), eigs , _ssmatrix (K )
488
480
489
- # Create back-up of arrays needed for later computations
490
- R_b = copy ( R )
491
- B_b = copy ( B )
492
- E_b = copy ( E )
493
- S_b = copy ( S )
481
+ # Make sure we can find the required slycot routine
482
+ try :
483
+ from slycot import sg02ad
484
+ except ImportError :
485
+ raise ControlSlycot ( "Can't find slycot module 'sg02ad'" )
494
486
495
487
# Solve the generalized algebraic Riccati equation by calling the
496
488
# Slycot function sg02ad
@@ -505,7 +497,7 @@ def care(A, B, Q, R=None, S=None, E=None, stabilizing=True, method=None,
505
497
L = np .array ([(alfar [i ] + alfai [i ]* 1j ) / beta [i ] for i in range (n )])
506
498
507
499
# Calculate the gain matrix G
508
- G = solve (R_b , B_b .T @ X @ E_b + S_b .T )
500
+ G = solve (R , B .T @ X @ E + S .T )
509
501
510
502
# Return the solution X, the closed-loop eigenvalues L and
511
503
# the gain matrix G
@@ -589,14 +581,11 @@ def dare(A, B, Q, R, S=None, E=None, stabilizing=True, method=None,
589
581
_check_shape (S_s , S , n , m )
590
582
591
583
# Figure out how to solve the problem
592
- if method == 'scipy' and not stabilizing :
593
- raise ControlArgument (
594
- "method='scipy' not valid when stabilizing is not True" )
595
-
596
- elif method == 'slycot' :
597
- return _dare_slycot (A , B , Q , R , S , E , stabilizing )
584
+ if method == 'scipy' :
585
+ if not stabilizing :
586
+ raise ControlArgument (
587
+ "method='scipy' not valid when stabilizing is not True" )
598
588
599
- else :
600
589
X = sp .linalg .solve_discrete_are (A , B , Q , R , e = E , s = S )
601
590
if S is None :
602
591
G = solve (B .T @ X @ B + R , B .T @ X @ A )
@@ -609,28 +598,12 @@ def dare(A, B, Q, R, S=None, E=None, stabilizing=True, method=None,
609
598
610
599
return _ssmatrix (X ), L , _ssmatrix (G )
611
600
612
-
613
- def _dare_slycot (A , B , Q , R , S = None , E = None , stabilizing = True ):
614
- # Make sure we can import required slycot routines
615
- try :
616
- from slycot import sb02md
617
- except ImportError :
618
- raise ControlSlycot ("Can't find slycot module 'sb02md'" )
619
-
620
- try :
621
- from slycot import sb02mt
622
- except ImportError :
623
- raise ControlSlycot ("Can't find slycot module 'sb02mt'" )
624
-
601
+ # Make sure we can import required slycot routine
625
602
try :
626
603
from slycot import sg02ad
627
604
except ImportError :
628
605
raise ControlSlycot ("Can't find slycot module 'sg02ad'" )
629
606
630
- # Determine main dimensions
631
- n = A .shape [0 ]
632
- m = B .shape [1 ]
633
-
634
607
# Initialize optional matrices
635
608
S = np .zeros ((n , m )) if S is None else np .array (S , ndmin = 2 )
636
609
E = np .eye (A .shape [0 ]) if E is None else np .array (E , ndmin = 2 )
0 commit comments