DirectSD-Python 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- directsd/__init__.py +141 -0
- directsd/analysis/__init__.py +4 -0
- directsd/analysis/charpol.py +89 -0
- directsd/analysis/errors.py +185 -0
- directsd/analysis/norms.py +630 -0
- directsd/design/__init__.py +9 -0
- directsd/design/convex.py +620 -0
- directsd/design/lifting.py +403 -0
- directsd/design/polynomial.py +5925 -0
- directsd/examples/__init__.py +0 -0
- directsd/examples/_common.py +36 -0
- directsd/examples/demos.py +1161 -0
- directsd/examples/examples.py +296 -0
- directsd/examples/help_examples.py +1043 -0
- directsd/glopt/__init__.py +4 -0
- directsd/glopt/advanced.py +1658 -0
- directsd/glopt/optimize.py +420 -0
- directsd/linalg/__init__.py +3 -0
- directsd/linalg/linsys.py +66 -0
- directsd/linalg/matrices.py +156 -0
- directsd/linalg/minreal.py +425 -0
- directsd/linalg/riccati.py +197 -0
- directsd/polynomial/__init__.py +11 -0
- directsd/polynomial/diophantine.py +426 -0
- directsd/polynomial/operations.py +247 -0
- directsd/polynomial/poln.py +742 -0
- directsd/polynomial/spectral.py +368 -0
- directsd/polynomial/transforms.py +124 -0
- directsd/polynomial/utils.py +449 -0
- directsd/sspace/__init__.py +4 -0
- directsd/sspace/design.py +1083 -0
- directsd/sspace/plant.py +198 -0
- directsd/tf/__init__.py +9 -0
- directsd/tf/interconnect.py +105 -0
- directsd/zpk/__init__.py +1 -0
- directsd/zpk/zpk.py +400 -0
- directsd_python-0.1.0.dist-info/METADATA +450 -0
- directsd_python-0.1.0.dist-info/RECORD +41 -0
- directsd_python-0.1.0.dist-info/WHEEL +5 -0
- directsd_python-0.1.0.dist-info/licenses/LICENSE +36 -0
- directsd_python-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1043 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Numerical examples from dsd_help.md — Python implementation.
|
|
3
|
+
|
|
4
|
+
Run all:
|
|
5
|
+
python -m directsd.examples.help_examples
|
|
6
|
+
Run one:
|
|
7
|
+
python -m directsd.examples.help_examples <name>
|
|
8
|
+
|
|
9
|
+
Note: norm values may differ from MATLAB due to different conventions.
|
|
10
|
+
sdh2/sdl2 for MIMO plants with P22≠0 currently fall back to a unit
|
|
11
|
+
controller (h2reg limitation); filtering examples (P22=0) work correctly.
|
|
12
|
+
Modal reduced-order controllers (modsdh2/modsdl2) always work.
|
|
13
|
+
"""
|
|
14
|
+
import sys
|
|
15
|
+
import math
|
|
16
|
+
import numpy as np
|
|
17
|
+
import scipy.signal as sig
|
|
18
|
+
|
|
19
|
+
from directsd import (
|
|
20
|
+
sfactor, sdh2, sdl2, sdahinf, sdahinorm, sdh2norm, sdhinorm,
|
|
21
|
+
sdl2err, sd2dof, sd2doferr, sdh2hinf, sdtrhinf, sdtrhinferr,
|
|
22
|
+
charpol, ch2, bilintr, dhinf, modsdh2, modsdl2,
|
|
23
|
+
GeneralizedPlant,
|
|
24
|
+
)
|
|
25
|
+
from directsd.analysis.norms import dahinorm as _dahinorm
|
|
26
|
+
from directsd.tf import to_lti, nd, mul, neg, add, feedback, nd_mul, nd_neg
|
|
27
|
+
from directsd.examples._common import cl_poles as _cl_poles, _z2zeta
|
|
28
|
+
|
|
29
|
+
# ---------------------------------------------------------------------------
|
|
30
|
+
# helpers
|
|
31
|
+
# ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
def _pade(tau, n):
|
|
34
|
+
"""Padé approximation for exp(-tau*s); returns (num, den) highest-power-first."""
|
|
35
|
+
c = [(-tau)**k / math.factorial(k) for k in range(2*n+2)]
|
|
36
|
+
num = np.zeros(n+1)
|
|
37
|
+
den = np.zeros(n+1)
|
|
38
|
+
for k in range(n+1):
|
|
39
|
+
coeff = (math.factorial(2*n - k) * math.factorial(n)
|
|
40
|
+
/ (math.factorial(2*n) * math.factorial(k) * math.factorial(n-k)))
|
|
41
|
+
num[k] = coeff * (-tau)**k
|
|
42
|
+
den[k] = coeff * tau**k
|
|
43
|
+
return num[::-1], den[::-1]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _zpk_str(obj):
|
|
48
|
+
"""Compact ZPK summary for display."""
|
|
49
|
+
if isinstance(obj, tuple) and len(obj) == 2:
|
|
50
|
+
n, d = obj
|
|
51
|
+
if not (np.isscalar(n) or isinstance(n, np.ndarray)):
|
|
52
|
+
return str(obj)
|
|
53
|
+
obj = sig.TransferFunction(np.atleast_1d(n).ravel(),
|
|
54
|
+
np.atleast_1d(d).ravel())
|
|
55
|
+
if hasattr(obj, 'to_zpk'):
|
|
56
|
+
zpk = obj.to_zpk()
|
|
57
|
+
z, p, k = zpk.zeros, zpk.poles, zpk.gain
|
|
58
|
+
elif isinstance(obj, (sig.lti, sig.TransferFunction)):
|
|
59
|
+
zpk = obj.to_zpk()
|
|
60
|
+
z, p, k = zpk.zeros, zpk.poles, zpk.gain
|
|
61
|
+
else:
|
|
62
|
+
return str(obj)
|
|
63
|
+
z_str = " ".join(f"{v:.4f}" for v in sorted(z, key=lambda x: x.real))
|
|
64
|
+
p_str = " ".join(f"{v:.4f}" for v in sorted(p, key=lambda x: x.real))
|
|
65
|
+
return f"k={k:.4f} zeros=[{z_str}] poles=[{p_str}]"
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _check(label, computed, expected, tol=0.01):
|
|
69
|
+
if not np.isfinite(computed):
|
|
70
|
+
print(f" SKIP {label}: computed={computed} MATLAB={expected:.6g} (nan/inf)")
|
|
71
|
+
return False
|
|
72
|
+
err = abs(computed - expected) / (abs(expected) + 1e-12)
|
|
73
|
+
status = "OK" if err < tol else "MISMATCH"
|
|
74
|
+
print(f" {status:8s} {label}: computed={computed:.6g} MATLAB={expected:.6g} "
|
|
75
|
+
f"rel_err={err:.3%}")
|
|
76
|
+
return status == "OK"
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# ---------------------------------------------------------------------------
|
|
82
|
+
# Example 1 – Basic getting-started example (line 181)
|
|
83
|
+
# F = 1/(25s^2+s), Fw = 2/(s+2), T=1
|
|
84
|
+
# sys = [F*Fw F; -F*Fw -F] (P22=-F, sdh2 via MIMO fallback)
|
|
85
|
+
# K_manual = (z-0.5)/(z-0.2), MATLAB sdh2norm(sys,K)=0.8332, opt=0.0292
|
|
86
|
+
# ---------------------------------------------------------------------------
|
|
87
|
+
def ex_getting_started():
|
|
88
|
+
print("\n=== Getting-started example ===")
|
|
89
|
+
F = sig.TransferFunction([1], [25, 1, 0])
|
|
90
|
+
Fw = sig.TransferFunction([2], [1, 2])
|
|
91
|
+
T = 1.0
|
|
92
|
+
sys = GeneralizedPlant([
|
|
93
|
+
[mul(F, Fw), F],
|
|
94
|
+
[neg(mul(F, Fw)), neg(F)],
|
|
95
|
+
])
|
|
96
|
+
|
|
97
|
+
# Characteristic polynomial for manually specified K
|
|
98
|
+
K_man = sig.dlti([1, -0.5], [1, -0.2], dt=T)
|
|
99
|
+
try:
|
|
100
|
+
cp = charpol(F, K_man)
|
|
101
|
+
print(f" charpol coeffs (manual K): {np.round(cp, 4)}")
|
|
102
|
+
print(f" MATLAB expected: [1, -2.1411, 1.3626, -0.2019]")
|
|
103
|
+
except Exception as e:
|
|
104
|
+
print(f" charpol: {e}")
|
|
105
|
+
|
|
106
|
+
# sdh2norm for manual K: use full sys (same as MATLAB sdh2norm(sys,K))
|
|
107
|
+
try:
|
|
108
|
+
norm_man = sdh2norm(sys, (K_man.num, K_man.den), T)
|
|
109
|
+
print(f" sdh2norm(sys, K_manual, T) = {norm_man:.4f} (MATLAB: 0.8332)")
|
|
110
|
+
except Exception as e:
|
|
111
|
+
print(f" sdh2norm manual: {e}")
|
|
112
|
+
|
|
113
|
+
# Optimal H2 design via full sys (P22=-F, may fall back)
|
|
114
|
+
K_opt, err_opt = sdh2(sys, T)
|
|
115
|
+
print(f" sdh2 K_opt: {_zpk_str(K_opt)}")
|
|
116
|
+
print(f" sdh2 cost: {err_opt:.4g} (MATLAB sdh2norm(sys,Kopt)=0.0292)")
|
|
117
|
+
try:
|
|
118
|
+
norm_opt = sdh2norm(sys, K_opt, T)
|
|
119
|
+
print(f" sdh2norm(sys, K_opt, T) = {norm_opt:.4f} (MATLAB: 0.0292)")
|
|
120
|
+
except Exception as e:
|
|
121
|
+
print(f" sdh2norm: {e}")
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# ---------------------------------------------------------------------------
|
|
125
|
+
# Example 2 – Deterministic / L2 tracking (line 333)
|
|
126
|
+
# F1=1/(25s+1), F2=1/s, R=1/s, rho=0.2, T=1
|
|
127
|
+
# MATLAB: sdl2err(sys,K)=3.2049
|
|
128
|
+
# ---------------------------------------------------------------------------
|
|
129
|
+
def ex_deterministic_l2():
|
|
130
|
+
print("\n=== Deterministic / L2 tracking (ship course, step) ===")
|
|
131
|
+
F1 = sig.TransferFunction([1], [25, 1])
|
|
132
|
+
F2 = sig.TransferFunction([1], [1, 0])
|
|
133
|
+
R = sig.TransferFunction([1], [1, 0])
|
|
134
|
+
rho = 0.2
|
|
135
|
+
T = 1.0
|
|
136
|
+
F_plant = mul(F2, F1)
|
|
137
|
+
sys = GeneralizedPlant([
|
|
138
|
+
[R, neg(F_plant)],
|
|
139
|
+
[0, rho],
|
|
140
|
+
[R, neg(F_plant)],
|
|
141
|
+
])
|
|
142
|
+
K, err = sdl2(sys, T)
|
|
143
|
+
print(f" sdl2 K: {_zpk_str(K)}")
|
|
144
|
+
print(f" sdl2 cost: {err:.4g}")
|
|
145
|
+
try:
|
|
146
|
+
err_check = sdl2err(sys, K, T) # pass full sys, same as MATLAB sdl2err(sys,K)
|
|
147
|
+
print(f" sdl2err(sys, K, T) = {err_check:.4f} (MATLAB: 3.2049)")
|
|
148
|
+
except Exception as e:
|
|
149
|
+
print(f" sdl2err: {e}")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
# ---------------------------------------------------------------------------
|
|
153
|
+
# Example 3 – Stochastic / H2 control (line 449)
|
|
154
|
+
# F=1/(25s^2+s), Fw=2/(s+2), rho=0.2, T=1
|
|
155
|
+
# MATLAB: sdh2norm(sys,K)^2=0.0328
|
|
156
|
+
# ---------------------------------------------------------------------------
|
|
157
|
+
def ex_stochastic_h2():
|
|
158
|
+
print("\n=== Stochastic / H2 control ===")
|
|
159
|
+
F = sig.TransferFunction([1], [25, 1, 0])
|
|
160
|
+
Fw = sig.TransferFunction([2], [1, 2])
|
|
161
|
+
rho = 0.2
|
|
162
|
+
T = 1.0
|
|
163
|
+
sys = GeneralizedPlant([
|
|
164
|
+
[mul(F, Fw), F],
|
|
165
|
+
[0, rho],
|
|
166
|
+
[neg(mul(F, Fw)), neg(F)],
|
|
167
|
+
])
|
|
168
|
+
K, err = sdh2(sys, T)
|
|
169
|
+
print(f" sdh2 K: {_zpk_str(K)}")
|
|
170
|
+
print(f" sdh2 cost^2: {err**2:.4g} (MATLAB: 0.0328)")
|
|
171
|
+
try:
|
|
172
|
+
norm_sq = sdh2norm(sys, K, T) ** 2
|
|
173
|
+
print(f" sdh2norm(sys,K,T)^2 = {norm_sq:.4f} (MATLAB: 0.0328)")
|
|
174
|
+
except Exception as e:
|
|
175
|
+
print(f" sdh2norm: {e}")
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# ---------------------------------------------------------------------------
|
|
179
|
+
# Example 4 – Reconstructing first-order process (line 697)
|
|
180
|
+
# F=1/(s+1), Sr=4/(−s^2+4), Fr=sfactor(Sr)=2/(s+2), T=0.1
|
|
181
|
+
# sys=[Fr 0 −F; Fr 1 0] (P22=0 → works)
|
|
182
|
+
# MATLAB: sdh2norm(sys,K)=0.7314, sdh2norm(sys,K,0)=0.7682
|
|
183
|
+
# ---------------------------------------------------------------------------
|
|
184
|
+
def ex_first_order_filter():
|
|
185
|
+
print("\n=== Reconstructing first-order process ===")
|
|
186
|
+
F = sig.TransferFunction([1], [1, 1])
|
|
187
|
+
Sr = sig.TransferFunction([4], [-1, 0, 4])
|
|
188
|
+
Fr_zpk, _ = sfactor(Sr)
|
|
189
|
+
Fr = Fr_zpk.to_tf()
|
|
190
|
+
T = 0.1
|
|
191
|
+
sys = GeneralizedPlant([
|
|
192
|
+
[Fr, 0, neg(F)],
|
|
193
|
+
[Fr, 1, 0],
|
|
194
|
+
])
|
|
195
|
+
K, err = sdh2(sys, T)
|
|
196
|
+
print(f" sdh2 K: {_zpk_str(K)}")
|
|
197
|
+
print(f" sdh2 cost: {err:.4f} (MATLAB sdh2norm avg=0.7314)")
|
|
198
|
+
try:
|
|
199
|
+
norm_avg = sdh2norm(sys, K, T)
|
|
200
|
+
print(f" sdh2norm(sys,K,T) avg = {norm_avg:.4f} (MATLAB: 0.7314)")
|
|
201
|
+
except Exception as e:
|
|
202
|
+
print(f" sdh2norm avg: {e}")
|
|
203
|
+
|
|
204
|
+
# Discrete-time optimal (minimize error at sampling instants only)
|
|
205
|
+
K0, err0 = sdh2(sys, T, t=0.0, method='pol')
|
|
206
|
+
print(f" sdh2 K0 (t=0, pol): {_zpk_str(K0)}")
|
|
207
|
+
print(f" sdh2 cost (t=0): {err0:.4f} (MATLAB sdh2norm(sys,K0,0)=0.7577)")
|
|
208
|
+
try:
|
|
209
|
+
norm0 = sdh2norm(sys, K0, T)
|
|
210
|
+
print(f" sdh2norm(sys,K0,T) avg = {norm0:.4f} (MATLAB: 0.7682)")
|
|
211
|
+
except Exception as e:
|
|
212
|
+
print(f" sdh2norm t=0: {e}")
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
# ---------------------------------------------------------------------------
|
|
216
|
+
# Example 5 – Filtering with delay (line 882)
|
|
217
|
+
# Same as Example 4 but F has iodelay=0.051, T=0.1
|
|
218
|
+
# MATLAB: sdh2norm avg=0.7879, t=0=0.7735
|
|
219
|
+
# ---------------------------------------------------------------------------
|
|
220
|
+
def ex_filter_with_delay():
|
|
221
|
+
print("\n=== Filtering with delay (τ=0.051) ===")
|
|
222
|
+
Sr = sig.TransferFunction([4], [-1, 0, 4])
|
|
223
|
+
Fr_zpk, _ = sfactor(Sr)
|
|
224
|
+
Fr = Fr_zpk.to_tf()
|
|
225
|
+
# F = 1/(s+1) with delay 0.051 — approximate with 2nd-order Padé
|
|
226
|
+
pn, pd = _pade(0.051, 2)
|
|
227
|
+
F_delay = sig.TransferFunction(np.polymul([1], pn),
|
|
228
|
+
np.polymul([1, 1], pd))
|
|
229
|
+
T = 0.1
|
|
230
|
+
sys = GeneralizedPlant([
|
|
231
|
+
[Fr, 0, neg(F_delay)],
|
|
232
|
+
[Fr, 1, 0],
|
|
233
|
+
])
|
|
234
|
+
K, err = sdh2(sys, T)
|
|
235
|
+
print(f" sdh2 K: {_zpk_str(K)}")
|
|
236
|
+
print(f" sdh2 cost: {err:.4f} (MATLAB sdh2norm avg≈0.7879)")
|
|
237
|
+
try:
|
|
238
|
+
norm_avg = sdh2norm(sys, K, T)
|
|
239
|
+
print(f" sdh2norm(sys,K,T) avg = {norm_avg:.4f} (MATLAB: 0.7879)")
|
|
240
|
+
except Exception as e:
|
|
241
|
+
print(f" sdh2norm: {e}")
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
# ---------------------------------------------------------------------------
|
|
245
|
+
# Example 6 – Reconstructing second-order process (line 1011)
|
|
246
|
+
# F=1/(s^2+s+1), same Fr, T=0.1
|
|
247
|
+
# MATLAB: sdh2norm avg=0.7738, t=0=0.7666
|
|
248
|
+
# ---------------------------------------------------------------------------
|
|
249
|
+
def ex_second_order_filter():
|
|
250
|
+
print("\n=== Reconstructing second-order process ===")
|
|
251
|
+
F = sig.TransferFunction([1], [1, 1, 1])
|
|
252
|
+
Sr = sig.TransferFunction([4], [-1, 0, 4])
|
|
253
|
+
Fr_zpk, _ = sfactor(Sr)
|
|
254
|
+
Fr = Fr_zpk.to_tf()
|
|
255
|
+
T = 0.1
|
|
256
|
+
sys = GeneralizedPlant([
|
|
257
|
+
[Fr, 0, neg(F)],
|
|
258
|
+
[Fr, 1, 0],
|
|
259
|
+
])
|
|
260
|
+
K, err = sdh2(sys, T)
|
|
261
|
+
print(f" sdh2 K: {_zpk_str(K)}")
|
|
262
|
+
print(f" sdh2 cost: {err:.4f} (MATLAB sdh2norm avg=0.7738)")
|
|
263
|
+
try:
|
|
264
|
+
norm_avg = sdh2norm(sys, K, T)
|
|
265
|
+
print(f" sdh2norm(sys,K,T) avg = {norm_avg:.4f} (MATLAB: 0.7738)")
|
|
266
|
+
except Exception as e:
|
|
267
|
+
print(f" sdh2norm: {e}")
|
|
268
|
+
|
|
269
|
+
K0, err0 = sdh2(sys, T, t=0.0, method='pol')
|
|
270
|
+
print(f" sdh2 K0 (t=0): {_zpk_str(K0)}")
|
|
271
|
+
print(f" sdh2 cost (t=0): {err0:.4f} (MATLAB sdh2norm K0 avg=0.9524)")
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
# ---------------------------------------------------------------------------
|
|
275
|
+
# Example 7 – Generalized hold (line 1140)
|
|
276
|
+
# Fr=2/(s+2), Fn=0.1, F=−1 (plant is -1), sys=[Fr 0 -1; Fr 0.1 0], T=0.2
|
|
277
|
+
# MATLAB: sdh2norm^2(ZOH)=0.3274, sdh2norm^2(gen hold)=0.3184
|
|
278
|
+
# ---------------------------------------------------------------------------
|
|
279
|
+
def ex_generalized_hold():
|
|
280
|
+
print("\n=== Generalized hold ===")
|
|
281
|
+
Sr = sig.TransferFunction([4], [-1, 0, 4])
|
|
282
|
+
Fr_zpk, _ = sfactor(Sr)
|
|
283
|
+
Fr = Fr_zpk.to_tf()
|
|
284
|
+
Fn = 0.1
|
|
285
|
+
T = 0.2
|
|
286
|
+
F_plant = sig.TransferFunction([-1], [1]) # plant = -1
|
|
287
|
+
|
|
288
|
+
sys = GeneralizedPlant([
|
|
289
|
+
[Fr, 0, F_plant], # z = Fr*w - 1*u (i.e. F_plant = -1)
|
|
290
|
+
[Fr, Fn, 0],
|
|
291
|
+
])
|
|
292
|
+
K0, err0 = sdh2(sys, T)
|
|
293
|
+
print(f" sdh2 K0 (ZOH): {_zpk_str(K0)}")
|
|
294
|
+
print(f" sdh2 cost^2 (ZOH): {err0**2:.4f} (MATLAB: 0.3274)")
|
|
295
|
+
try:
|
|
296
|
+
norm0_sq = sdh2norm(F_plant, K0, T) ** 2
|
|
297
|
+
print(f" sdh2norm(F,K0,T)^2 = {norm0_sq:.4f}")
|
|
298
|
+
except Exception as e:
|
|
299
|
+
print(f" sdh2norm ZOH: {e}")
|
|
300
|
+
|
|
301
|
+
H = sig.TransferFunction([1], [1, 2])
|
|
302
|
+
K, err = sdh2(sys, T, H=H)
|
|
303
|
+
print(f" sdh2 K (gen. hold): {_zpk_str(K)}")
|
|
304
|
+
print(f" sdh2 cost^2 (gen hold): {err**2:.4f} (MATLAB: 0.3184)")
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
# ---------------------------------------------------------------------------
|
|
308
|
+
# Example 8 – Optimal disturbance attenuation (line 1315)
|
|
309
|
+
# F=(s+0.5)/(s^2−s), Fw=2/(s+2), τ=0.093, T=0.2
|
|
310
|
+
# MATLAB: sdh2norm avg=0.1840, t=0=0.1600
|
|
311
|
+
# ---------------------------------------------------------------------------
|
|
312
|
+
def ex_disturbance_attenuation():
|
|
313
|
+
print("\n=== Optimal disturbance attenuation (with delay τ=0.093) ===")
|
|
314
|
+
F = sig.TransferFunction([1, 0.5], [1, -1, 0])
|
|
315
|
+
Fw = sig.TransferFunction([2], [1, 2])
|
|
316
|
+
T = 0.2
|
|
317
|
+
# F with delay 0.093 — 2nd-order Padé approx
|
|
318
|
+
pn, pd = _pade(0.093, 2)
|
|
319
|
+
Fd = sig.TransferFunction(np.polymul([1, 0.5], pn),
|
|
320
|
+
np.polymul([1, -1, 0], pd))
|
|
321
|
+
sys = GeneralizedPlant([
|
|
322
|
+
[mul(F, Fw), Fd],
|
|
323
|
+
[neg(mul(F, Fw)), neg(Fd)],
|
|
324
|
+
])
|
|
325
|
+
K, err = sdh2(sys, T)
|
|
326
|
+
print(f" sdh2 K: {_zpk_str(K)}")
|
|
327
|
+
print(f" sdh2 cost: {err:.4f} (MATLAB sdh2norm avg≈0.1840)")
|
|
328
|
+
try:
|
|
329
|
+
norm_avg = sdh2norm(Fd, K, T)
|
|
330
|
+
print(f" sdh2norm(Fd,K,T) avg = {norm_avg:.4f}")
|
|
331
|
+
except Exception as e:
|
|
332
|
+
print(f" sdh2norm: {e}")
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
# ---------------------------------------------------------------------------
|
|
336
|
+
# Example 9 – Optimal ship course stabilization (line 1465)
|
|
337
|
+
# F=0.051/(25s^2+s), Sw given, Fw=sfactor(Sw), rho=sqrt(0.1), T=1
|
|
338
|
+
# MATLAB: sdh2norm=0.0190
|
|
339
|
+
# ---------------------------------------------------------------------------
|
|
340
|
+
def ex_ship_course():
|
|
341
|
+
print("\n=== Optimal ship course stabilization ===")
|
|
342
|
+
F = sig.TransferFunction([0.051], [25, 1, 0])
|
|
343
|
+
Sw = sig.TransferFunction([0.0757], [1, 0, 2.489, 0, 1.848])
|
|
344
|
+
Fw_zpk, _ = sfactor(Sw)
|
|
345
|
+
Fw = Fw_zpk.to_tf()
|
|
346
|
+
rho = np.sqrt(0.1)
|
|
347
|
+
T = 1.0
|
|
348
|
+
sys = GeneralizedPlant([
|
|
349
|
+
[mul(F, Fw), F],
|
|
350
|
+
[0, rho],
|
|
351
|
+
[neg(mul(F, Fw)), neg(F)],
|
|
352
|
+
])
|
|
353
|
+
K, err = sdh2(sys, T)
|
|
354
|
+
print(f" sdh2 K: {_zpk_str(K)}")
|
|
355
|
+
print(f" sdh2 cost: {err:.4f} (MATLAB sdh2norm=0.0190)")
|
|
356
|
+
try:
|
|
357
|
+
norm = sdh2norm(F, K, T)
|
|
358
|
+
print(f" sdh2norm(F,K,T) = {norm:.4f}")
|
|
359
|
+
except Exception as e:
|
|
360
|
+
print(f" sdh2norm: {e}")
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
# ---------------------------------------------------------------------------
|
|
364
|
+
# Example 10 – Double integrator H2 control (line 1587)
|
|
365
|
+
# F=1/s^2, rho=1, T=0.1
|
|
366
|
+
# ---------------------------------------------------------------------------
|
|
367
|
+
def ex_double_integrator():
|
|
368
|
+
print("\n=== Double integrator H2 control ===")
|
|
369
|
+
F = sig.TransferFunction([1], [1, 0, 0])
|
|
370
|
+
rho = 1.0
|
|
371
|
+
T = 0.1
|
|
372
|
+
sys = GeneralizedPlant([
|
|
373
|
+
[neg(F), neg(F)],
|
|
374
|
+
[0, rho],
|
|
375
|
+
[neg(F), neg(F)],
|
|
376
|
+
])
|
|
377
|
+
Kopt, err_opt = sdh2(sys, T)
|
|
378
|
+
print(f" sdh2 Kopt: {_zpk_str(Kopt)}")
|
|
379
|
+
print(f" sdh2 cost: {err_opt:.4g}")
|
|
380
|
+
poles = _cl_poles(F, Kopt, T)
|
|
381
|
+
if len(poles) > 0:
|
|
382
|
+
stable = all(abs(r) < 1.0 for r in poles)
|
|
383
|
+
print(f" closed-loop poles: {[f'{r:.4f}' for r in poles]}")
|
|
384
|
+
print(f" stable: {stable} (MATLAB: True)")
|
|
385
|
+
|
|
386
|
+
# Redesign method — ch2 + bilintr
|
|
387
|
+
try:
|
|
388
|
+
Kc_raw, _ = ch2(sys)
|
|
389
|
+
Kc = sig.TransferFunction(*Kc_raw)
|
|
390
|
+
Kc2d_nd = bilintr(Kc, 'tustin', T)
|
|
391
|
+
Kc2d = sig.TransferFunction(*Kc2d_nd)
|
|
392
|
+
poles2d = _cl_poles(F, Kc2d_nd, T)
|
|
393
|
+
if len(poles2d) > 0:
|
|
394
|
+
stable2d = all(abs(r) < 1.0 for r in poles2d)
|
|
395
|
+
print(f" redesign poles: {[f'{r:.4f}' for r in poles2d]}")
|
|
396
|
+
print(f" redesign stable: {stable2d} (MATLAB: False – marginal)")
|
|
397
|
+
except Exception as e:
|
|
398
|
+
print(f" redesign: skipped ({e})")
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
# ---------------------------------------------------------------------------
|
|
402
|
+
# Example 11 – L2-optimal tracking (line 1792)
|
|
403
|
+
# R=1/s, F=1/(5s^2+s), Q=1/(s+1), T=0.2
|
|
404
|
+
# MATLAB: sdl2err=4.6824e-4
|
|
405
|
+
# ---------------------------------------------------------------------------
|
|
406
|
+
def ex_l2_tracking():
|
|
407
|
+
print("\n=== L2-optimal tracking ===")
|
|
408
|
+
R = sig.TransferFunction([1], [1, 0])
|
|
409
|
+
F = sig.TransferFunction([1], [5, 1, 0])
|
|
410
|
+
Q = sig.TransferFunction([1], [1, 1])
|
|
411
|
+
T = 0.2
|
|
412
|
+
sys = GeneralizedPlant([
|
|
413
|
+
[mul(Q, R), neg(F)],
|
|
414
|
+
[R, neg(F)],
|
|
415
|
+
])
|
|
416
|
+
Kopt, err = sdl2(sys, T)
|
|
417
|
+
print(f" sdl2 Kopt: {_zpk_str(Kopt)}")
|
|
418
|
+
print(f" sdl2 cost: {err:.4g} (MATLAB sdl2err=4.6824e-4)")
|
|
419
|
+
try:
|
|
420
|
+
err_check = sdl2err(sys, Kopt, T)
|
|
421
|
+
print(f" sdl2err(sys, K, T) = {err_check:.4e} (MATLAB: 4.6824e-4)")
|
|
422
|
+
except Exception as e:
|
|
423
|
+
print(f" sdl2err: {e}")
|
|
424
|
+
|
|
425
|
+
poles = _cl_poles(F, Kopt, T)
|
|
426
|
+
if len(poles) > 0:
|
|
427
|
+
stable = all(abs(r) < 1.0 for r in poles)
|
|
428
|
+
print(f" closed-loop poles: {[f'{r:.4f}' for r in poles]}")
|
|
429
|
+
print(f" stable: {stable} (MATLAB: True)")
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
# ---------------------------------------------------------------------------
|
|
433
|
+
# Example 12 – L2-optimal redesign (line 2037)
|
|
434
|
+
# F=10/(s^2+s), Kc=(0.416s+1)/(0.139s+1), τ=0.01, T=0.04
|
|
435
|
+
# MATLAB: sdl2err=6.7103e-7
|
|
436
|
+
# ---------------------------------------------------------------------------
|
|
437
|
+
def ex_l2_redesign():
|
|
438
|
+
print("\n=== L2-optimal redesign ===")
|
|
439
|
+
R = sig.TransferFunction([1], [1, 0])
|
|
440
|
+
F_ct = sig.TransferFunction([10], [1, 1, 0])
|
|
441
|
+
Kc = sig.TransferFunction([0.416, 1], [0.139, 1])
|
|
442
|
+
Q = feedback(mul(F_ct, Kc))
|
|
443
|
+
T = 0.04
|
|
444
|
+
|
|
445
|
+
# MATLAB: F.iodelay = 0.01, handled EXACTLY inside sdl2 via the modified
|
|
446
|
+
# Z-transform (udelay). A Padé substitute in the DESIGN plant introduces
|
|
447
|
+
# fast poles (~±600) whose discretized images span ~20 decades and
|
|
448
|
+
# destroy the polynomial pipeline — pass the delay separately.
|
|
449
|
+
tau = 0.01
|
|
450
|
+
sys_design = GeneralizedPlant([
|
|
451
|
+
[mul(Q, R), neg(F_ct)],
|
|
452
|
+
[R, neg(F_ct)],
|
|
453
|
+
])
|
|
454
|
+
K, err = sdl2(sys_design, T, udelay=tau)
|
|
455
|
+
print(f" sdl2 K: {_zpk_str(K)}")
|
|
456
|
+
print(f" MATLAB K: 4.0371 z(z-0.9608)(z-0.9083)(z^2-0.0708z+0.07494)")
|
|
457
|
+
print(f" /((z+0.04358)(z-0.009759)(z+0.4438)(z-0.7342)(z-0.9559))")
|
|
458
|
+
|
|
459
|
+
# Verification: sdl2err has no delay support, so evaluate on a
|
|
460
|
+
# Padé-approximated plant (fine for EVALUATION — MATLAB's documented K
|
|
461
|
+
# scores 7.9e-7 on it, matching the documented 6.7103e-7).
|
|
462
|
+
pn, pd = _pade(tau, 2)
|
|
463
|
+
F_delay = sig.TransferFunction(np.polymul([10], pn),
|
|
464
|
+
np.polymul([1, 1, 0], pd))
|
|
465
|
+
sys_eval = GeneralizedPlant([
|
|
466
|
+
[mul(Q, R), neg(F_delay)],
|
|
467
|
+
[R, neg(F_delay)],
|
|
468
|
+
])
|
|
469
|
+
try:
|
|
470
|
+
err_check = sdl2err(sys_eval, K, T)
|
|
471
|
+
print(f" sdl2err(Padé sys, K, T) = {err_check:.4e} (MATLAB: 6.7103e-7)")
|
|
472
|
+
except Exception as e:
|
|
473
|
+
print(f" sdl2err: {e}")
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
# ---------------------------------------------------------------------------
|
|
477
|
+
# Example 13 – 2-DOF optimal tracking (line 2159)
|
|
478
|
+
# R=1/s, F=1/(s-1), Q=1/(s+2), T=0.5
|
|
479
|
+
# MATLAB: 1-DOF sdl2err=2.5845, 2-DOF sd2doferr=5.6599e-4
|
|
480
|
+
# ---------------------------------------------------------------------------
|
|
481
|
+
def ex_2dof_tracking():
|
|
482
|
+
print("\n=== 2-DOF optimal tracking ===")
|
|
483
|
+
R = sig.TransferFunction([1], [1, 0])
|
|
484
|
+
F = sig.TransferFunction([1], [1, -1])
|
|
485
|
+
Q = sig.TransferFunction([1], [1, 2])
|
|
486
|
+
T = 0.5
|
|
487
|
+
sys = GeneralizedPlant([
|
|
488
|
+
[mul(Q, R), neg(F)],
|
|
489
|
+
[R, neg(F)],
|
|
490
|
+
])
|
|
491
|
+
K1, err1 = sdl2(sys, T)
|
|
492
|
+
print(f" 1-DOF sdl2 K1: {_zpk_str(K1)}")
|
|
493
|
+
print(f" 1-DOF sdl2 cost: {err1:.4g} (MATLAB sdl2err=2.5845)")
|
|
494
|
+
try:
|
|
495
|
+
err_1dof = sdl2err(sys, K1, T)
|
|
496
|
+
print(f" sdl2err(sys, K1, T) = {err_1dof:.4f} (MATLAB: 2.5845)")
|
|
497
|
+
except Exception as e:
|
|
498
|
+
print(f" sdl2err 1-DOF: {e}")
|
|
499
|
+
|
|
500
|
+
# 2-DOF: sd2dof takes SISO plant F; sd2doferr takes full 3x2 generalized plant
|
|
501
|
+
# sys_2dof rows: [performance Q*R*d-F*u; reference measurement R*d; output measurement -F*u]
|
|
502
|
+
sys_2dof = GeneralizedPlant([
|
|
503
|
+
[mul(Q, R), neg(F)],
|
|
504
|
+
[R, 0 ],
|
|
505
|
+
[0, neg(F) ],
|
|
506
|
+
], n_meas=2)
|
|
507
|
+
try:
|
|
508
|
+
KR, err_2dof = sd2dof(sys_2dof, K1, T)
|
|
509
|
+
print(f" 2-DOF KR: {_zpk_str(KR)}")
|
|
510
|
+
print(f" 2-DOF sd2dof cost: {err_2dof:.4e} (MATLAB: 5.6599e-4)")
|
|
511
|
+
err2 = sd2doferr(sys_2dof, K1, KR, T)
|
|
512
|
+
_check("2-DOF sd2doferr", err2, 5.6599e-4, tol=0.50)
|
|
513
|
+
except Exception as e:
|
|
514
|
+
print(f" sd2dof/sd2doferr: {e}")
|
|
515
|
+
|
|
516
|
+
|
|
517
|
+
# ---------------------------------------------------------------------------
|
|
518
|
+
# Example 14 – AHinf-optimal prediction (line 2341)
|
|
519
|
+
# F=1/(s+1), Fr=1/(5s+1), predict τ=0.15, T=0.1
|
|
520
|
+
# MATLAB: sdahinorm=0.0351
|
|
521
|
+
# ---------------------------------------------------------------------------
|
|
522
|
+
def ex_ahinf_prediction():
|
|
523
|
+
print("\n=== AHinf-optimal prediction ===")
|
|
524
|
+
F = sig.TransferFunction([1], [1, 1])
|
|
525
|
+
Fr = sig.TransferFunction([1], [5, 1])
|
|
526
|
+
# Q = exp(+0.15s) — Padé: exp(+tau*s) ≈ den/num of exp(-tau*s)
|
|
527
|
+
pn, pd = _pade(0.15, 2)
|
|
528
|
+
Q_num, Q_den = pd, pn # flip for positive delay
|
|
529
|
+
T = 0.1
|
|
530
|
+
sys = GeneralizedPlant([
|
|
531
|
+
[sig.TransferFunction(np.polymul(-Q_num, [1]), np.polymul(Q_den, [5, 1])),
|
|
532
|
+
F],
|
|
533
|
+
[Fr, 0],
|
|
534
|
+
])
|
|
535
|
+
K, err = sdahinf(sys, T)
|
|
536
|
+
print(f" sdahinf K: {_zpk_str(K)}")
|
|
537
|
+
try:
|
|
538
|
+
ahinf_norm = sdahinorm(F, K, T)
|
|
539
|
+
print(f" sdahinorm(F,K,T) = {ahinf_norm:.4f} (MATLAB: 0.0351)")
|
|
540
|
+
except Exception as e:
|
|
541
|
+
print(f" sdahinorm: {e}")
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
# ---------------------------------------------------------------------------
|
|
545
|
+
# Example 15 – Discrete AHinf example 1
|
|
546
|
+
# T=1, F=z/(−2z+1), Fw=(z−2)/(−2z+1), V1=V2=1
|
|
547
|
+
# Generalised plant: [[Fw,F],[0,V2],[-Fw,-F]] (z-domain, 3×2)
|
|
548
|
+
# MATLAB (Source/dsd_help.md, verbatim): K = dhinf(sys) = 1.5 (constant!),
|
|
549
|
+
# dahinorm(sys,K) = 3.6056. The "~0.9487" figure previously here was NOT a
|
|
550
|
+
# real MATLAB value -- it was Python's own (buggy) dhinf lam matching its
|
|
551
|
+
# own (also-buggy, K-independent) dahinorm, a self-consistent-but-wrong
|
|
552
|
+
# pair. dahinorm is now correctly K-dependent; the remaining mismatch below
|
|
553
|
+
# is real (dhinf/_polhinf still doesn't find MATLAB's true optimal K here).
|
|
554
|
+
# ---------------------------------------------------------------------------
|
|
555
|
+
|
|
556
|
+
def ex_dhinf_example1():
|
|
557
|
+
print("\n=== Discrete AHinf – example 1 ===")
|
|
558
|
+
T = 1.0
|
|
559
|
+
F = ([1, 0], [-2, 1]) # z / (-2z+1)
|
|
560
|
+
Fw = ([1, -2], [-2, 1]) # (z-2) / (-2z+1)
|
|
561
|
+
V1, V2 = ([1], [1]), ([1], [1])
|
|
562
|
+
# Build 3x2 generalised plant
|
|
563
|
+
sys_plant = [
|
|
564
|
+
[(nd_mul(V1, Fw)), (nd_mul(V1, F))],
|
|
565
|
+
[([0], [1]), V2 ],
|
|
566
|
+
[(nd_neg(Fw)), (nd_neg(F)) ],
|
|
567
|
+
]
|
|
568
|
+
try:
|
|
569
|
+
sys_conv = _z2zeta(sys_plant)
|
|
570
|
+
K, err_dh = dhinf(sys_conv, T=T)
|
|
571
|
+
print(f" dhinf K: {_zpk_str(K)}")
|
|
572
|
+
print(f" dhinf lam = {err_dh:.4f} (MATLAB: K=1.5 constant, dahinorm=3.6056)")
|
|
573
|
+
err_da = _dahinorm(sys_conv, K, T)
|
|
574
|
+
print(f" dahinorm = {err_da:.4f}")
|
|
575
|
+
_check("dhinf lam consistent with dahinorm", err_dh, err_da, tol=0.15)
|
|
576
|
+
except Exception as e:
|
|
577
|
+
print(f" dhinf: {e}")
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
# ---------------------------------------------------------------------------
|
|
581
|
+
# Example 16 – Discrete AHinf example 2 (generic case)
|
|
582
|
+
# T=1, F2=1/(−z²−2.1z+1), F1=(2z²+z), Fw=(0.3z+1)
|
|
583
|
+
# Generalised plant: [[F2*Fw, F2*F1],[0,V2],[-F2*Fw,-F2*F1]]
|
|
584
|
+
# MATLAB: dhinf errOpt ~ 2.1244
|
|
585
|
+
# ---------------------------------------------------------------------------
|
|
586
|
+
def ex_dhinf_example2():
|
|
587
|
+
print("\n=== Discrete AHinf – example 2 (generic) ===")
|
|
588
|
+
T = 1.0
|
|
589
|
+
F2 = ([1], [-1, -2.1, 1])
|
|
590
|
+
F1 = ([2, 1, 0],[1] )
|
|
591
|
+
Fw = ([0.3, 1], [1] )
|
|
592
|
+
V1, V2 = ([1],[1]), ([1],[1])
|
|
593
|
+
F2Fw = nd_mul(F2, Fw)
|
|
594
|
+
F2F1 = nd_mul(F2, F1)
|
|
595
|
+
sys_plant = [
|
|
596
|
+
[(nd_mul(V1, F2Fw)), (nd_mul(V1, F2F1))],
|
|
597
|
+
[([0], [1]), V2 ],
|
|
598
|
+
[(nd_neg(F2Fw)), (nd_neg(F2F1)) ],
|
|
599
|
+
]
|
|
600
|
+
try:
|
|
601
|
+
sys_conv = _z2zeta(sys_plant)
|
|
602
|
+
K, err_dh = dhinf(sys_conv, T=T)
|
|
603
|
+
print(f" dhinf K: {_zpk_str(K)}")
|
|
604
|
+
print(f" dhinf lam = {err_dh:.4f} (MATLAB ~2.1244)")
|
|
605
|
+
err_da = _dahinorm(sys_conv, K, T)
|
|
606
|
+
print(f" dahinorm = {err_da:.4f}")
|
|
607
|
+
_check("dhinf lam (tol 50%)", err_dh, 2.1244, tol=0.50)
|
|
608
|
+
except Exception as e:
|
|
609
|
+
print(f" dhinf: {e}")
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
# ---------------------------------------------------------------------------
|
|
613
|
+
# Example 17 – H2 and AHinf optimal control (line 2647)
|
|
614
|
+
# F1=0.051/(25s+1), F2=1/s, rho=0.1, T=1
|
|
615
|
+
# MATLAB: sdh2norm(K2)=3.2563, sdahinorm(K2)=11.4122, sdhinorm(K2)=11.4082
|
|
616
|
+
# sdh2norm(Kinf)=7.6683, sdahinorm(Kinf)=7.6683, sdhinorm(Kinf)=7.6628
|
|
617
|
+
# ---------------------------------------------------------------------------
|
|
618
|
+
def ex_h2_ahinf_control():
|
|
619
|
+
print("\n=== H2 and AHinf optimal control ===")
|
|
620
|
+
F1 = sig.TransferFunction([0.051], [25, 1])
|
|
621
|
+
F2 = sig.TransferFunction([1], [1, 0])
|
|
622
|
+
F_plant = mul(F2, F1)
|
|
623
|
+
rho = 0.1
|
|
624
|
+
T = 1.0
|
|
625
|
+
sys = GeneralizedPlant([
|
|
626
|
+
[neg(F2), neg(F_plant)],
|
|
627
|
+
[0, rho],
|
|
628
|
+
[neg(F2), neg(F_plant)],
|
|
629
|
+
])
|
|
630
|
+
K2, err_h2 = sdh2(sys, T)
|
|
631
|
+
print(f" H2-optimal K2: {_zpk_str(K2)}")
|
|
632
|
+
print(f" sdh2 cost: {err_h2:.4g} (MATLAB sdh2norm=3.2563)")
|
|
633
|
+
try:
|
|
634
|
+
ah_K2 = sdahinorm(sys, K2, T)
|
|
635
|
+
print(f" sdahinorm(sys,K2,T) = {ah_K2:.4f} (MATLAB: 11.4122)")
|
|
636
|
+
# sdhinorm(sys, ...) -- the FULL generalized plant, matching MATLAB's
|
|
637
|
+
# sdhinorm(sys, K2). Python's sdhinorm is currently an AHinf alias,
|
|
638
|
+
# so this prints the same value as sdahinorm above, not MATLAB's true
|
|
639
|
+
# 11.4082 -- a documented, deliberate scope decision, not a bug.
|
|
640
|
+
hinf_K2 = sdhinorm(sys, K2, T)[0]
|
|
641
|
+
print(f" sdhinorm(sys,K2,T) = {hinf_K2:.4f} (MATLAB: 11.4082; Python's"
|
|
642
|
+
" sdhinorm = AHinf alias)")
|
|
643
|
+
except Exception as e:
|
|
644
|
+
print(f" norm eval: {e}")
|
|
645
|
+
|
|
646
|
+
Kinf, err_inf = sdahinf(sys, T)
|
|
647
|
+
print(f" AHinf-optimal Kinf: {_zpk_str(Kinf)}")
|
|
648
|
+
print(f" sdahinf cost: {err_inf:.4g} (MATLAB sdh2norm(Kinf)=7.6683)")
|
|
649
|
+
try:
|
|
650
|
+
ah_inf = sdahinorm(sys, Kinf, T)
|
|
651
|
+
print(f" sdahinorm(sys,Kinf,T) = {ah_inf:.4f} (MATLAB: 7.6683)")
|
|
652
|
+
except Exception as e:
|
|
653
|
+
print(f" sdahinorm Kinf: {e}")
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
# ---------------------------------------------------------------------------
|
|
657
|
+
# Example 18 – Mixed H2/AHinf optimization (line 2807)
|
|
658
|
+
# F=1/(5s^2+s), kappa=1, T=1
|
|
659
|
+
# MATLAB: sdh2norm(KH2)=0.8153, sdahinorm(KH2)=1.7326
|
|
660
|
+
# sdh2norm(Kinf)=1.2251, sdahinorm(Kinf)=1.2251
|
|
661
|
+
# sdh2norm(Kmix)=0.9498, sdahinorm(Kmix)=1.3436
|
|
662
|
+
# ---------------------------------------------------------------------------
|
|
663
|
+
def ex_mixed_h2_ahinf():
|
|
664
|
+
print("\n=== Mixed H2/AHinf optimization ===")
|
|
665
|
+
F = sig.TransferFunction([1], [5, 1, 0])
|
|
666
|
+
kappa = 1.0
|
|
667
|
+
T = 1.0
|
|
668
|
+
sys = GeneralizedPlant([
|
|
669
|
+
[neg(F), neg(F)],
|
|
670
|
+
[0, kappa],
|
|
671
|
+
[neg(F), neg(F)],
|
|
672
|
+
])
|
|
673
|
+
KH2, err_H2 = sdh2(sys, T)
|
|
674
|
+
print(f" H2-optimal KH2: {_zpk_str(KH2)}")
|
|
675
|
+
print(f" sdh2 cost: {err_H2:.4g} (MATLAB sdh2norm=0.8153)")
|
|
676
|
+
try:
|
|
677
|
+
ah_KH2 = sdahinorm(F, KH2, T)
|
|
678
|
+
print(f" sdahinorm(F,KH2,T) = {ah_KH2:.4f} (MATLAB: 1.7326)")
|
|
679
|
+
except Exception as e:
|
|
680
|
+
print(f" sdahinorm KH2: {e}")
|
|
681
|
+
|
|
682
|
+
Kinf, err_Kinf = sdahinf(sys, T)
|
|
683
|
+
print(f" AHinf-optimal Kinf: {_zpk_str(Kinf)}")
|
|
684
|
+
try:
|
|
685
|
+
ah_Kinf = sdahinorm(F, Kinf, T)
|
|
686
|
+
print(f" sdahinorm(F,Kinf,T) = {ah_Kinf:.4f} (MATLAB: 1.2251)")
|
|
687
|
+
except Exception as e:
|
|
688
|
+
print(f" sdahinorm Kinf: {e}")
|
|
689
|
+
|
|
690
|
+
try:
|
|
691
|
+
Kmix, err_mix = sdh2hinf(sys, T, 0.5, 2, 1)
|
|
692
|
+
print(f" Mixed Kmix (rho=0.5): {_zpk_str(Kmix)}")
|
|
693
|
+
ah_mix = sdahinorm(F, Kmix, T)
|
|
694
|
+
print(f" sdahinorm(F,Kmix,T) = {ah_mix:.4f} (MATLAB: 1.3436)")
|
|
695
|
+
except Exception as e:
|
|
696
|
+
print(f" sdh2hinf/sdahinorm: {e}")
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
# ---------------------------------------------------------------------------
|
|
700
|
+
# Example 19 – L2 and AHinf optimal tracking (line 2975)
|
|
701
|
+
# R=1/s, F=1/(4s^2+0.5s+1), rho=0.12, T=1
|
|
702
|
+
# MATLAB: sdl2err(K2)=1.0321, sdtrhinferr(K2)=1.2213
|
|
703
|
+
# sdl2err(Kinf)=1.1118, sdtrhinferr(Kinf)=1.0544
|
|
704
|
+
# ---------------------------------------------------------------------------
|
|
705
|
+
def ex_l2_ahinf_tracking():
|
|
706
|
+
print("\n=== L2 and AHinf optimal tracking ===")
|
|
707
|
+
R = sig.TransferFunction([1], [1, 0])
|
|
708
|
+
F = sig.TransferFunction([1], [4, 0.5, 1])
|
|
709
|
+
rho = 0.12
|
|
710
|
+
T = 1.0
|
|
711
|
+
sys = GeneralizedPlant([
|
|
712
|
+
[R, neg(F)],
|
|
713
|
+
[mul(rho, R), neg(rho)],
|
|
714
|
+
[R, neg(F)],
|
|
715
|
+
])
|
|
716
|
+
K2, err2 = sdl2(sys, T)
|
|
717
|
+
print(f" L2-optimal K2: {_zpk_str(K2)}")
|
|
718
|
+
print(f" sdl2 cost: {err2:.4g} (MATLAB sdl2err=1.0321)")
|
|
719
|
+
try:
|
|
720
|
+
l2_K2 = sdl2err(sys, K2, T)
|
|
721
|
+
print(f" sdl2err(sys,K2,T) = {l2_K2:.4f} (MATLAB: 1.0321)")
|
|
722
|
+
ah_K2 = sdtrhinferr(sys, K2, T)
|
|
723
|
+
print(f" sdtrhinferr = {ah_K2:.4f} (MATLAB: 1.2213)")
|
|
724
|
+
except Exception as e:
|
|
725
|
+
print(f" norm eval: {e}")
|
|
726
|
+
|
|
727
|
+
try:
|
|
728
|
+
Kinf, err_tr = sdtrhinf(sys, T)
|
|
729
|
+
print(f" AHinf-optimal Kinf: {_zpk_str(Kinf)}")
|
|
730
|
+
l2_inf = sdl2err(sys, Kinf, T)
|
|
731
|
+
print(f" sdl2err(sys,Kinf,T) = {l2_inf:.4f} (MATLAB: 1.1118)")
|
|
732
|
+
ah_inf = sdtrhinferr(sys, Kinf, T)
|
|
733
|
+
print(f" sdtrhinferr(Kinf) = {ah_inf:.4f} (MATLAB: 1.0544)")
|
|
734
|
+
except Exception as e:
|
|
735
|
+
print(f" sdtrhinf: {e}")
|
|
736
|
+
|
|
737
|
+
|
|
738
|
+
# ---------------------------------------------------------------------------
|
|
739
|
+
# Example 20 – H2-optimal preview control (line 3135)
|
|
740
|
+
# Fr=1/(5s+1), Fn=0.2, F=1/(s-1) with delay 1.5, Q=exp(-2s)
|
|
741
|
+
# sys=[Q*Fr 0 -F; Fr Fn -F], T=1
|
|
742
|
+
# MATLAB: sdh2norm(sys,K)^2=11.6701
|
|
743
|
+
# ---------------------------------------------------------------------------
|
|
744
|
+
def ex_h2_preview():
|
|
745
|
+
print("\n=== H2-optimal preview control ===")
|
|
746
|
+
Fr = sig.TransferFunction([1], [5, 1])
|
|
747
|
+
Fn = 0.2
|
|
748
|
+
# F = 1/(s-1) with delay 1.5 → 3rd-order Padé
|
|
749
|
+
pn15, pd15 = _pade(1.5, 3)
|
|
750
|
+
F_delay = sig.TransferFunction(np.polymul([1], pn15),
|
|
751
|
+
np.polymul([1, -1], pd15))
|
|
752
|
+
# Q = exp(-2s) → 3rd-order Padé
|
|
753
|
+
pn2, pd2 = _pade(2.0, 3)
|
|
754
|
+
Q = sig.TransferFunction(pn2, pd2)
|
|
755
|
+
T = 1.0
|
|
756
|
+
sys = GeneralizedPlant([
|
|
757
|
+
[mul(Q, Fr), 0, neg(F_delay)],
|
|
758
|
+
[Fr, Fn, neg(F_delay)],
|
|
759
|
+
])
|
|
760
|
+
K, err = sdh2(sys, T)
|
|
761
|
+
print(f" sdh2 K: {_zpk_str(K)}")
|
|
762
|
+
print(f" sdh2 cost^2: {err**2:.4f} (MATLAB: 11.6701)")
|
|
763
|
+
try:
|
|
764
|
+
norm_sq = sdh2norm(F_delay, K, T) ** 2
|
|
765
|
+
print(f" sdh2norm(F_delay,K,T)^2 = {norm_sq:.4f}")
|
|
766
|
+
except Exception as e:
|
|
767
|
+
print(f" sdh2norm: {e}")
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
# ---------------------------------------------------------------------------
|
|
771
|
+
# Example 21 – L2-optimal preview control (line 3243)
|
|
772
|
+
# R=1/(s^2+s), F=1/(5s+1) with delay 1.5, Q=1/(0.1s+1)
|
|
773
|
+
# preview=2 -- MATLAB removes the non-causal preview block by placing the
|
|
774
|
+
# delay in the ideal operator instead (Q.iodelay=preview) plus a remainder
|
|
775
|
+
# delay on R (R.iodelay=theta); see sdl2's refdelay parameter, which
|
|
776
|
+
# applies this sigma/theta split internally via the EXACT modified
|
|
777
|
+
# Z-transform (no Pade approximation needed -- unlike the delay-free
|
|
778
|
+
# F.iodelay=1.5, handled via udelay).
|
|
779
|
+
# sys=[Q*R -F; R -F], T=1
|
|
780
|
+
# MATLAB: sdl2err=0.0517
|
|
781
|
+
# ---------------------------------------------------------------------------
|
|
782
|
+
def ex_l2_preview():
|
|
783
|
+
print("\n=== L2-optimal preview control ===")
|
|
784
|
+
R = sig.TransferFunction([1], [1, 1, 0])
|
|
785
|
+
F = sig.TransferFunction([1], [5, 1])
|
|
786
|
+
Q = sig.TransferFunction([1], [0.1, 1])
|
|
787
|
+
T = 1.0
|
|
788
|
+
sys = GeneralizedPlant([
|
|
789
|
+
[mul(Q, R), neg(F)],
|
|
790
|
+
[R, neg(F)],
|
|
791
|
+
])
|
|
792
|
+
K, err = sdl2(sys, T, udelay=1.5, refdelay=2.0)
|
|
793
|
+
print(f" sdl2 K: {_zpk_str(K)}")
|
|
794
|
+
print(f" sdl2 cost: {err:.4f} (MATLAB sdl2err=0.0517)")
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
# ---------------------------------------------------------------------------
|
|
798
|
+
# Example 22 – Optimal 2-DOF preview control (line 3387)
|
|
799
|
+
# Same plant setup as example 21 (exNo=2's unstable F=1/(5s-1) branch,
|
|
800
|
+
# matching demo_2dofp.m); 1-DOF K from sdl2, then KR from sd2dof.
|
|
801
|
+
# MATLAB: 1-DOF sdl2err=2.7072, 2-DOF sd2doferr=0.0602
|
|
802
|
+
# ---------------------------------------------------------------------------
|
|
803
|
+
def ex_2dof_preview():
|
|
804
|
+
print("\n=== Optimal 2-DOF preview control ===")
|
|
805
|
+
R = sig.TransferFunction([1], [1, 1, 0])
|
|
806
|
+
F = sig.TransferFunction([1], [5, -1])
|
|
807
|
+
Q = sig.TransferFunction([1], [0.1, 1])
|
|
808
|
+
T = 1.0
|
|
809
|
+
# 1-DOF system: exact delay support via sdl2's udelay/refdelay (see
|
|
810
|
+
# ex_l2_preview) -- no Pade approximation needed.
|
|
811
|
+
sys = GeneralizedPlant([
|
|
812
|
+
[mul(Q, R), neg(F)],
|
|
813
|
+
[R, neg(F)],
|
|
814
|
+
])
|
|
815
|
+
K, err_1dof = sdl2(sys, T, udelay=1.5, refdelay=2.0)
|
|
816
|
+
print(f" 1-DOF K: {_zpk_str(K)}")
|
|
817
|
+
print(f" 1-DOF sdl2 cost: {err_1dof:.4f} (MATLAB sdl2err=2.7072)")
|
|
818
|
+
|
|
819
|
+
# 2-DOF feedforward (sd2dof): exact delay support via the same
|
|
820
|
+
# udelay/refdelay mechanism (sd2dof/_sd2dofcoef).
|
|
821
|
+
sys_2dof = GeneralizedPlant([
|
|
822
|
+
[mul(Q, R), neg(F)],
|
|
823
|
+
[R, 0],
|
|
824
|
+
[0, neg(F)],
|
|
825
|
+
], n_meas=2)
|
|
826
|
+
KR, err_2dof = sd2dof(sys_2dof, K, T, udelay=1.5, refdelay=2.0)
|
|
827
|
+
print(f" 2-DOF KR: {_zpk_str(KR)}")
|
|
828
|
+
print(f" 2-DOF sd2dof cost: {err_2dof:.4f} (MATLAB sd2doferr=0.0602)")
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
# ---------------------------------------------------------------------------
|
|
832
|
+
# Example 23 – Reduced-order H2-optimal control (line 3556)
|
|
833
|
+
# Ship course stabilization; F=0.051/(25s^2+s), T=1
|
|
834
|
+
# Full-order H2 optimal, then reduced order 1 via modsdh2
|
|
835
|
+
# MATLAB: full sdh2norm=0.0190, reduced cost≈0.0193
|
|
836
|
+
# ---------------------------------------------------------------------------
|
|
837
|
+
def ex_reduced_h2():
|
|
838
|
+
print("\n=== Reduced-order H2-optimal control (ship course) ===")
|
|
839
|
+
F = sig.TransferFunction([0.051], [25, 1, 0])
|
|
840
|
+
Sw = sig.TransferFunction([0.0757], [1, 0, 2.489, 0, 1.848])
|
|
841
|
+
Fw_zpk, _ = sfactor(Sw)
|
|
842
|
+
Fw = Fw_zpk.to_tf()
|
|
843
|
+
rho = np.sqrt(0.1)
|
|
844
|
+
T = 1.0
|
|
845
|
+
sys = GeneralizedPlant([
|
|
846
|
+
[mul(F, Fw), F],
|
|
847
|
+
[0, rho],
|
|
848
|
+
[neg(mul(F, Fw)), neg(F)],
|
|
849
|
+
])
|
|
850
|
+
# Full-order optimal
|
|
851
|
+
Kopt, err_opt = sdh2(sys, T)
|
|
852
|
+
print(f" Full-order Kopt: {_zpk_str(Kopt)}")
|
|
853
|
+
print(f" Full-order cost: {err_opt:.4f} (MATLAB sdh2norm=0.0190)")
|
|
854
|
+
|
|
855
|
+
# Reduced-order via modsdh2 with full generalized plant (P22 extracted internally)
|
|
856
|
+
print(" Searching reduced-order (ord=1, global randsearch)...")
|
|
857
|
+
Kred, cost_red = modsdh2(sys, T, ord_K=1, alpha=0.0, beta=np.inf,
|
|
858
|
+
method='randsearch', n_iter=500)
|
|
859
|
+
print(f" Reduced-order K (ord=1): {_zpk_str(Kred)}")
|
|
860
|
+
print(f" Reduced-order cost: {cost_red:.4f} (MATLAB cost≈0.0193)")
|
|
861
|
+
|
|
862
|
+
# Local refinement
|
|
863
|
+
Kloc, cost_loc = modsdh2(sys, T, ord_K=1, alpha=0.0, beta=np.inf,
|
|
864
|
+
method='dual_annealing', n_iter=200)
|
|
865
|
+
print(f" After local opt: K = {_zpk_str(Kloc)}")
|
|
866
|
+
print(f" Local opt cost: {cost_loc:.4f}")
|
|
867
|
+
|
|
868
|
+
|
|
869
|
+
# ---------------------------------------------------------------------------
|
|
870
|
+
# Example 24 – Optimal integral control (line 3725)
|
|
871
|
+
# F1=0.0694/(18.22s+1), F2=1/s, Fw given, rho=2, T=2
|
|
872
|
+
# Full-order K marginally stable (z=1 pole); reduced order with integrator
|
|
873
|
+
# MATLAB: full sdh2norm=7.2492 (marginal), reduced cost≈8.4768
|
|
874
|
+
# ---------------------------------------------------------------------------
|
|
875
|
+
def ex_integral_control():
|
|
876
|
+
print("\n=== Optimal integral control ===")
|
|
877
|
+
F1 = sig.TransferFunction([0.0694], [18.22, 1])
|
|
878
|
+
F2 = sig.TransferFunction([1], [1, 0])
|
|
879
|
+
lam = 0.3; w0 = 0.3; sigma_w = 7.25
|
|
880
|
+
Fw = sig.TransferFunction([2*lam*w0*sigma_w, 0], [1, 2*lam*w0, w0**2])
|
|
881
|
+
rho = 2.0
|
|
882
|
+
T = 2.0
|
|
883
|
+
F_plant = mul(F2, F1)
|
|
884
|
+
sys = GeneralizedPlant([
|
|
885
|
+
[mul(F2, Fw), F_plant],
|
|
886
|
+
[0, rho],
|
|
887
|
+
[neg(mul(F2, Fw)), neg(F_plant)],
|
|
888
|
+
])
|
|
889
|
+
# Full-order optimal (will have z=1 pole → marginally stable)
|
|
890
|
+
Kopt, err_opt = sdh2(sys, T)
|
|
891
|
+
print(f" Full-order Kopt: {_zpk_str(Kopt)}")
|
|
892
|
+
print(f" Full-order cost: {err_opt:.4f} (MATLAB sdh2norm=7.2492, marginal)")
|
|
893
|
+
|
|
894
|
+
# Reduced-order with integrator constraint via modsdh2
|
|
895
|
+
# Note: Python modsdh2 uses modal parameterization (no explicit dK0 constraint)
|
|
896
|
+
# We require ord=2 and alpha=0.02, beta=2 to force stable controller
|
|
897
|
+
print(" Searching reduced-order with integrator (ord=2, alpha=0.02, beta=2)...")
|
|
898
|
+
Kred, cost_red = modsdh2(sys, T, ord_K=2, alpha=0.02, beta=2,
|
|
899
|
+
method='randsearch', n_iter=800)
|
|
900
|
+
print(f" Reduced-order K (ord=2): {_zpk_str(Kred)}")
|
|
901
|
+
print(f" Reduced-order cost: {cost_red:.4f} (MATLAB cost≈8.4768)")
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
# ---------------------------------------------------------------------------
|
|
905
|
+
# Example 25 – Reduced-order L2-optimal control (line 3920)
|
|
906
|
+
# R=1/s, F=10/(2s^2+s), Q=1/(s+1)^2, T=0.2
|
|
907
|
+
# Full-order sdl2err≈1.2116e-8, reduced order 1 modsdl2 cost≈4.752e-7
|
|
908
|
+
# ---------------------------------------------------------------------------
|
|
909
|
+
def ex_reduced_l2():
|
|
910
|
+
print("\n=== Reduced-order L2-optimal control ===")
|
|
911
|
+
R = sig.TransferFunction([1], [1, 0])
|
|
912
|
+
F = sig.TransferFunction([10], [2, 1, 0])
|
|
913
|
+
Q = sig.TransferFunction([1], [1, 2, 1])
|
|
914
|
+
T = 0.2
|
|
915
|
+
sys = GeneralizedPlant([
|
|
916
|
+
[mul(Q, R), neg(F)],
|
|
917
|
+
[R, neg(F)],
|
|
918
|
+
])
|
|
919
|
+
# Full-order optimal
|
|
920
|
+
Kopt, err_opt = sdl2(sys, T)
|
|
921
|
+
print(f" Full-order Kopt: {_zpk_str(Kopt)}")
|
|
922
|
+
print(f" Full-order cost: {err_opt:.4e} (MATLAB sdl2err≈1.2116e-8)")
|
|
923
|
+
try:
|
|
924
|
+
err_full = sdl2err(sys, Kopt, T)
|
|
925
|
+
print(f" sdl2err(sys,Kopt,T) = {err_full:.4e} (MATLAB: 1.2116e-8)")
|
|
926
|
+
except Exception as e:
|
|
927
|
+
print(f" sdl2err: {e}")
|
|
928
|
+
|
|
929
|
+
# Reduced-order via modsdl2 with full generalized plant
|
|
930
|
+
print(" Searching reduced-order (ord=1, alpha=0.1)...")
|
|
931
|
+
Kred, cost_red = modsdl2(sys, T, ord_K=1, alpha=0.1, beta=np.inf,
|
|
932
|
+
method='randsearch', n_iter=500)
|
|
933
|
+
print(f" Reduced-order K (ord=1): {_zpk_str(Kred)}")
|
|
934
|
+
print(f" Reduced-order cost: {cost_red:.4e} (MATLAB cost≈4.752e-7)")
|
|
935
|
+
|
|
936
|
+
Kloc, cost_loc = modsdl2(sys, T, ord_K=1, alpha=0.1, beta=np.inf,
|
|
937
|
+
method='dual_annealing', n_iter=300)
|
|
938
|
+
print(f" After local opt: K = {_zpk_str(Kloc)}")
|
|
939
|
+
print(f" Local opt cost: {cost_loc:.4e}")
|
|
940
|
+
|
|
941
|
+
|
|
942
|
+
# ---------------------------------------------------------------------------
|
|
943
|
+
# Example 26 – Reduced-order redesign (line 4101)
|
|
944
|
+
# F=1/(s^2-s), Kc=(5s+1)/(s+3), Q=feedback(F*Kc,1), R=1/s, T=0.5
|
|
945
|
+
# Full-order sdl2err≈2.7771e-4, reduced order 2 modsdl2 cost≈0.0059
|
|
946
|
+
# ---------------------------------------------------------------------------
|
|
947
|
+
def ex_reduced_redesign():
|
|
948
|
+
print("\n=== Reduced-order redesign ===")
|
|
949
|
+
R = sig.TransferFunction([1], [1, 0])
|
|
950
|
+
F = sig.TransferFunction([1], [1, -1, 0])
|
|
951
|
+
Kc = sig.TransferFunction([5, 1], [1, 3])
|
|
952
|
+
Q = feedback(mul(F, Kc))
|
|
953
|
+
T = 0.5
|
|
954
|
+
sys = GeneralizedPlant([
|
|
955
|
+
[mul(add(Q, neg(F)), R), F],
|
|
956
|
+
[mul(F, R), neg(F)],
|
|
957
|
+
])
|
|
958
|
+
# Full-order optimal
|
|
959
|
+
Kopt, err_opt = sdl2(sys, T)
|
|
960
|
+
print(f" Full-order Kopt: {_zpk_str(Kopt)}")
|
|
961
|
+
print(f" Full-order cost: {err_opt:.4e} (MATLAB sdl2err≈2.7771e-4)")
|
|
962
|
+
try:
|
|
963
|
+
err_full = sdl2err(sys, Kopt, T)
|
|
964
|
+
print(f" sdl2err(sys,Kopt,T) = {err_full:.4e} (MATLAB: 2.7771e-4)")
|
|
965
|
+
except Exception as e:
|
|
966
|
+
print(f" sdl2err: {e}")
|
|
967
|
+
|
|
968
|
+
# Reduced-order via modsdl2 with full generalized plant
|
|
969
|
+
print(" Searching reduced-order (ord=2, alpha=0.001)...")
|
|
970
|
+
Kred, cost_red = modsdl2(sys, T, ord_K=2, alpha=0.001, beta=np.inf,
|
|
971
|
+
method='randsearch', n_iter=800)
|
|
972
|
+
print(f" Reduced-order K (ord=2): {_zpk_str(Kred)}")
|
|
973
|
+
print(f" Reduced-order cost: {cost_red:.4f} (MATLAB cost≈0.0059)")
|
|
974
|
+
|
|
975
|
+
Kloc, cost_loc = modsdl2(sys, T, ord_K=2, alpha=0.001, beta=np.inf,
|
|
976
|
+
method='dual_annealing', n_iter=400)
|
|
977
|
+
print(f" After local opt: K = {_zpk_str(Kloc)}")
|
|
978
|
+
print(f" Local opt cost: {cost_loc:.4f}")
|
|
979
|
+
|
|
980
|
+
|
|
981
|
+
# ---------------------------------------------------------------------------
|
|
982
|
+
# registry & runner
|
|
983
|
+
# ---------------------------------------------------------------------------
|
|
984
|
+
|
|
985
|
+
_ALL = {
|
|
986
|
+
"getting_started": ex_getting_started,
|
|
987
|
+
"deterministic_l2": ex_deterministic_l2,
|
|
988
|
+
"stochastic_h2": ex_stochastic_h2,
|
|
989
|
+
"first_order_filter": ex_first_order_filter,
|
|
990
|
+
"filter_with_delay": ex_filter_with_delay,
|
|
991
|
+
"second_order_filter": ex_second_order_filter,
|
|
992
|
+
"generalized_hold": ex_generalized_hold,
|
|
993
|
+
"disturbance_atten": ex_disturbance_attenuation,
|
|
994
|
+
"ship_course": ex_ship_course,
|
|
995
|
+
"double_integrator": ex_double_integrator,
|
|
996
|
+
"l2_tracking": ex_l2_tracking,
|
|
997
|
+
"l2_redesign": ex_l2_redesign,
|
|
998
|
+
"2dof_tracking": ex_2dof_tracking,
|
|
999
|
+
"ahinf_prediction": ex_ahinf_prediction,
|
|
1000
|
+
"dhinf_ex1": ex_dhinf_example1,
|
|
1001
|
+
"dhinf_ex2": ex_dhinf_example2,
|
|
1002
|
+
"h2_ahinf_control": ex_h2_ahinf_control,
|
|
1003
|
+
"mixed_h2_ahinf": ex_mixed_h2_ahinf,
|
|
1004
|
+
"l2_ahinf_tracking": ex_l2_ahinf_tracking,
|
|
1005
|
+
"h2_preview": ex_h2_preview,
|
|
1006
|
+
"l2_preview": ex_l2_preview,
|
|
1007
|
+
"2dof_preview": ex_2dof_preview,
|
|
1008
|
+
"reduced_h2": ex_reduced_h2,
|
|
1009
|
+
"integral_control": ex_integral_control,
|
|
1010
|
+
"reduced_l2": ex_reduced_l2,
|
|
1011
|
+
"reduced_redesign": ex_reduced_redesign,
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
def main():
|
|
1016
|
+
import warnings
|
|
1017
|
+
warnings.filterwarnings('ignore')
|
|
1018
|
+
names = sys.argv[1:]
|
|
1019
|
+
if names:
|
|
1020
|
+
for n in names:
|
|
1021
|
+
if n in _ALL:
|
|
1022
|
+
try:
|
|
1023
|
+
_ALL[n]()
|
|
1024
|
+
except Exception as e:
|
|
1025
|
+
print(f" ERROR in {n}: {e}")
|
|
1026
|
+
import traceback; traceback.print_exc()
|
|
1027
|
+
else:
|
|
1028
|
+
print(f"Unknown example '{n}'. Available: {list(_ALL)}")
|
|
1029
|
+
else:
|
|
1030
|
+
fail = 0
|
|
1031
|
+
for name, fn in _ALL.items():
|
|
1032
|
+
try:
|
|
1033
|
+
fn()
|
|
1034
|
+
except Exception as e:
|
|
1035
|
+
print(f"\n ERROR in {name}: {e}")
|
|
1036
|
+
import traceback; traceback.print_exc()
|
|
1037
|
+
fail += 1
|
|
1038
|
+
print(f"\n{'='*60}")
|
|
1039
|
+
print(f"Ran {len(_ALL)} examples, {fail} errors")
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
if __name__ == "__main__":
|
|
1043
|
+
main()
|