Skip to content

Commit 99e49d9

Browse files
author
Henrik Sandberg
committed
Added in sysnorm.py:
* type check when calling ct.norm * metod argument in ct.norm (slycot or scipy) using function _slycot_or_scipy from ct.mateqn Change in sysnorm_test.py * set print_warning=False
1 parent f60c83a commit 99e49d9

File tree

2 files changed

+42
-33
lines changed

2 files changed

+42
-33
lines changed

control/sysnorm.py

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,19 @@ def _h2norm_slycot(sys, print_warning=True):
2727
2828
See also
2929
--------
30-
slycot.ab13bd : the Slycot routine that does the calculation
31-
https://github.com/python-control/Slycot/issues/199 : Post on issue with ab13bf
30+
``slycot.ab13bd`` : the Slycot routine that does the calculation
31+
https://github.com/python-control/Slycot/issues/199 : Post on issue with ``ab13bf``
3232
"""
3333

3434
try:
3535
from slycot import ab13bd
3636
except ImportError:
37-
ct.ControlSlycot("Can't find slycot module 'ab13bd'!")
37+
ct.ControlSlycot("Can't find slycot module ``ab13bd``!")
3838

3939
try:
4040
from slycot.exceptions import SlycotArithmeticError
4141
except ImportError:
42-
raise ct.ControlSlycot("Can't find slycot class 'SlycotArithmeticError'!")
42+
raise ct.ControlSlycot("Can't find slycot class ``SlycotArithmeticError``!")
4343

4444
A, B, C, D = ct.ssdata(ct.ss(sys))
4545

@@ -83,7 +83,7 @@ def _h2norm_slycot(sys, print_warning=True):
8383

8484
#------------------------------------------------------------------------------
8585

86-
def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
86+
def norm(system, p=2, tol=1e-10, print_warning=True, method=None):
8787
"""Computes norm of system.
8888
8989
Parameters
@@ -97,13 +97,15 @@ def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
9797
unless p='inf'.
9898
print_warning : bool
9999
Print warning message in case norm value may be uncertain.
100-
use_slycot : bool
101-
Use Slycot routines if available.
100+
method : str, optional
101+
Set the method used for computing the result. Current methods are
102+
'slycot' and 'scipy'. If set to None (default), try 'slycot' first
103+
and then 'scipy'.
102104
103105
Returns
104106
-------
105-
norm_value : float or NoneType
106-
Norm value of system (float) or None if computation could not be completed.
107+
norm_value : float
108+
Norm value of system.
107109
108110
Notes
109111
-----
@@ -112,17 +114,24 @@ def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
112114
Examples
113115
--------
114116
>>> Gc = ct.tf([1], [1, 2, 1])
115-
>>> ct.norm(Gc,2)
117+
>>> ct.norm(Gc, 2)
116118
0.5000000000000001
117-
>>> ct.norm(Gc,'inf',tol=1e-10)
118-
1.0000000000582077
119+
>>> ct.norm(Gc, 'inf', tol=1e-11, method='scipy')
120+
1.000000000007276
119121
"""
122+
123+
if not isinstance(system, (ct.StateSpace, ct.TransferFunction)):
124+
raise TypeError('Parameter ``system``: must be a ``StateSpace`` or ``TransferFunction``')
125+
120126
G = ct.ss(system)
121127
A = G.A
122128
B = G.B
123129
C = G.C
124130
D = G.D
125131

132+
# Decide what method to use
133+
method = ct.mateqn._slycot_or_scipy(method)
134+
126135
# -------------------
127136
# H2 norm computation
128137
# -------------------
@@ -149,12 +158,12 @@ def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
149158

150159
else:
151160
# Use slycot, if available, to compute (finite) norm
152-
if ct.slycot_check() and use_slycot:
161+
if method == 'slycot':
153162
return _h2norm_slycot(G, print_warning)
154163

155164
# Else use scipy
156165
else:
157-
P = ct.lyap(A, B@B.T) # Solve for controllability Gramian
166+
P = ct.lyap(A, B@B.T, method=method) # Solve for controllability Gramian
158167

159168
# System is stable to reach this point, and P should be positive semi-definite.
160169
# Test next is a precaution in case the Lyapunov equation is ill conditioned.
@@ -187,12 +196,12 @@ def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
187196

188197
else:
189198
# Use slycot, if available, to compute (finite) norm
190-
if ct.slycot_check() and use_slycot:
199+
if method == 'slycot':
191200
return _h2norm_slycot(G, print_warning)
192201

193202
# Else use scipy
194203
else:
195-
P = ct.dlyap(A, B@B.T)
204+
P = ct.dlyap(A, B@B.T, method=method)
196205

197206
# System is stable to reach this point, and P should be positive semi-definite.
198207
# Test next is a precaution in case the Lyapunov equation is ill conditioned.
@@ -226,7 +235,7 @@ def norm(system, p=2, tol=1e-10, print_warning=True, use_slycot=True):
226235
return float('inf')
227236

228237
# Use slycot, if available, to compute (finite) norm
229-
if ct.slycot_check() and use_slycot:
238+
if method == 'slycot':
230239
return ct.linfnorm(G, tol)[0]
231240

232241
# Else use scipy

control/tests/sysnorm_test.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,35 @@ def test_norm_1st_order_stable_system():
1313
"""First-order stable continuous-time system"""
1414
s = ct.tf('s')
1515
G1 = 1/(s+1)
16-
assert np.allclose(ct.norm(G1, p='inf', tol=1e-9), 1.0) # Comparison to norm computed in MATLAB
17-
assert np.allclose(ct.norm(G1, p=2), 0.707106781186547) # Comparison to norm computed in MATLAB
16+
assert np.allclose(ct.norm(G1, p='inf', tol=1e-9, print_warning=False), 1.0) # Comparison to norm computed in MATLAB
17+
assert np.allclose(ct.norm(G1, p=2, print_warning=False), 0.707106781186547) # Comparison to norm computed in MATLAB
1818

1919
Gd1 = ct.sample_system(G1, 0.1)
20-
assert np.allclose(ct.norm(Gd1, p='inf', tol=1e-9), 1.0) # Comparison to norm computed in MATLAB
21-
assert np.allclose(ct.norm(Gd1, p=2), 0.223513699524858) # Comparison to norm computed in MATLAB
20+
assert np.allclose(ct.norm(Gd1, p='inf', tol=1e-9, print_warning=False), 1.0) # Comparison to norm computed in MATLAB
21+
assert np.allclose(ct.norm(Gd1, p=2, print_warning=False), 0.223513699524858) # Comparison to norm computed in MATLAB
2222

2323

2424
def test_norm_1st_order_unstable_system():
2525
"""First-order unstable continuous-time system"""
2626
s = ct.tf('s')
2727
G2 = 1/(1-s)
28-
assert np.allclose(ct.norm(G2, p='inf', tol=1e-9), 1.0) # Comparison to norm computed in MATLAB
29-
assert ct.norm(G2, p=2) == float('inf') # Comparison to norm computed in MATLAB
28+
assert np.allclose(ct.norm(G2, p='inf', tol=1e-9, print_warning=False), 1.0) # Comparison to norm computed in MATLAB
29+
assert ct.norm(G2, p=2, print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
3030

3131
Gd2 = ct.sample_system(G2, 0.1)
32-
assert np.allclose(ct.norm(Gd2, p='inf', tol=1e-9), 1.0) # Comparison to norm computed in MATLAB
33-
assert ct.norm(Gd2, p=2) == float('inf') # Comparison to norm computed in MATLAB
32+
assert np.allclose(ct.norm(Gd2, p='inf', tol=1e-9, print_warning=False), 1.0) # Comparison to norm computed in MATLAB
33+
assert ct.norm(Gd2, p=2, print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
3434

3535
def test_norm_2nd_order_system_imag_poles():
3636
"""Second-order continuous-time system with poles on imaginary axis"""
3737
s = ct.tf('s')
3838
G3 = 1/(s**2+1)
39-
assert ct.norm(G3, p='inf') == float('inf') # Comparison to norm computed in MATLAB
40-
assert ct.norm(G3, p=2) == float('inf') # Comparison to norm computed in MATLAB
39+
assert ct.norm(G3, p='inf', print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
40+
assert ct.norm(G3, p=2, print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
4141

4242
Gd3 = ct.sample_system(G3, 0.1)
43-
assert ct.norm(Gd3, p='inf') == float('inf') # Comparison to norm computed in MATLAB
44-
assert ct.norm(Gd3, p=2) == float('inf') # Comparison to norm computed in MATLAB
43+
assert ct.norm(Gd3, p='inf', print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
44+
assert ct.norm(Gd3, p=2, print_warning=False) == float('inf') # Comparison to norm computed in MATLAB
4545

4646
def test_norm_3rd_order_mimo_system():
4747
"""Third-order stable MIMO continuous-time system"""
@@ -55,9 +55,9 @@ def test_norm_3rd_order_mimo_system():
5555
[-0.863652821988714, -1.214117043615409, -0.006849328103348]])
5656
D = np.zeros((2,2))
5757
G4 = ct.ss(A,B,C,D) # Random system generated in MATLAB
58-
assert np.allclose(ct.norm(G4, p='inf', tol=1e-9), 4.276759162964244) # Comparison to norm computed in MATLAB
59-
assert np.allclose(ct.norm(G4, p=2), 2.237461821810309) # Comparison to norm computed in MATLAB
58+
assert np.allclose(ct.norm(G4, p='inf', tol=1e-9, print_warning=False), 4.276759162964244) # Comparison to norm computed in MATLAB
59+
assert np.allclose(ct.norm(G4, p=2, print_warning=False), 2.237461821810309) # Comparison to norm computed in MATLAB
6060

6161
Gd4 = ct.sample_system(G4, 0.1)
62-
assert np.allclose(ct.norm(Gd4, p='inf', tol=1e-9), 4.276759162964228) # Comparison to norm computed in MATLAB
63-
assert np.allclose(ct.norm(Gd4, p=2), 0.707434962289554) # Comparison to norm computed in MATLAB
62+
assert np.allclose(ct.norm(Gd4, p='inf', tol=1e-9, print_warning=False), 4.276759162964228) # Comparison to norm computed in MATLAB
63+
assert np.allclose(ct.norm(Gd4, p=2, print_warning=False), 0.707434962289554) # Comparison to norm computed in MATLAB

0 commit comments

Comments
 (0)