Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4242976

Browse files
authored
Merge pull request#1185 from roryyorke/rory/test-markers-2
pytest marks for slycot, part 2
2 parents2435a6a +faaa40e commit4242976

File tree

12 files changed

+289
-211
lines changed

12 files changed

+289
-211
lines changed

‎control/tests/conftest.py‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
importcontrol
88

99
defpytest_runtest_setup(item):
10-
if (notcontrol.exception.slycot_check()
11-
andany(mark.name=='slycot'
12-
formarkinitem.iter_markers())):
13-
pytest.skip("slycot not installed")
10+
ifnotcontrol.exception.slycot_check():
11+
ifany(mark.name=='slycot'
12+
formarkinitem.iter_markers()):
13+
pytest.skip("slycot not installed")
14+
elifany(mark.name=='noslycot'
15+
formarkinitem.iter_markers()):
16+
# used, e.g., for tests checking ControlSlycot
17+
pytest.skip("slycot installed")
1418

1519
if (notcontrol.exception.cvxopt_check()
1620
andany(mark.name=='cvxopt'

‎control/tests/convert_test.py‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,13 @@
2121
fromcontrolimportrss,ss,ss2tf,tf,tf2ss
2222
fromcontrol.statefbkimportctrb,obsv
2323
fromcontrol.freqplotimportbode
24-
fromcontrol.exceptionimportslycot_check,ControlMIMONotImplemented
24+
fromcontrol.exceptionimportControlMIMONotImplemented
2525

2626

2727
# Set to True to print systems to the output.
2828
verbose=False
2929
# Maximum number of states to test + 1
3030
maxStates=4
31-
# Maximum number of inputs and outputs to test + 1
32-
# If slycot is not installed, just check SISO
33-
maxIO=5ifslycot_check()else2
3431

3532

3633
@pytest.fixture
@@ -49,8 +46,13 @@ def printSys(self, sys, ind):
4946

5047
@pytest.mark.usefixtures("legacy_plot_signature")
5148
@pytest.mark.parametrize("states",range(1,maxStates))
52-
@pytest.mark.parametrize("inputs",range(1,maxIO))
53-
@pytest.mark.parametrize("outputs",range(1,maxIO))
49+
# If slycot is not installed, just check SISO
50+
@pytest.mark.parametrize("inputs",
51+
[1]+ [pytest.param(i,marks=pytest.mark.slycot)
52+
foriinrange(2,5)])
53+
@pytest.mark.parametrize("outputs",
54+
[1]+ [pytest.param(i,marks=pytest.mark.slycot)
55+
foriinrange(2,5)])
5456
deftestConvert(self,fixedseed,states,inputs,outputs):
5557
"""Test state space to transfer function conversion.
5658
@@ -147,7 +149,11 @@ def testConvert(self, fixedseed, states, inputs, outputs):
147149
np.testing.assert_array_almost_equal(
148150
ssorig_imag,tfxfrm_imag,decimal=5)
149151

150-
deftestConvertMIMO(self):
152+
153+
@pytest.mark.parametrize('have_slycot',
154+
[pytest.param(True,marks=pytest.mark.slycot),
155+
pytest.param(False,marks=pytest.mark.noslycot)])
156+
deftestConvertMIMO(self,have_slycot):
151157
"""Test state space to transfer function conversion.
152158
153159
Do a MIMO conversion and make sure that it is processed
@@ -165,7 +171,7 @@ def testConvertMIMO(self):
165171
[0.008,1.39,48.78]]])
166172

167173
# Convert to state space and look for an error
168-
if(notslycot_check()):
174+
ifnothave_slycot:
169175
withpytest.raises(ControlMIMONotImplemented):
170176
tf2ss(tsys)
171177
else:

‎control/tests/interconnect_test.py‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,12 @@ def test_summation_exceptions():
5656
ct.summing_junction('u','y',dimension=False)
5757

5858

59-
@pytest.mark.parametrize("dim", [1,3])
59+
@pytest.mark.parametrize("dim",
60+
[1,pytest.param(3,marks=pytest.mark.slycot)])
6061
deftest_interconnect_implicit(dim):
6162
"""Test the use of implicit connections in interconnect()"""
6263
importrandom
6364

64-
ifdim!=1andnotct.slycot_check():
65-
pytest.xfail("slycot not installed")
66-
6765
# System definition
6866
P=ct.rss(2,dim,dim,strictly_proper=True,name='P')
6967

‎control/tests/lti_test.py‎

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
importcontrolasct
99
fromcontrolimportNonlinearIOSystem,c2d,common_timebase,isctime, \
1010
isdtime,issiso,ss,tf,tf2ss
11-
fromcontrol.exceptionimportslycot_check
1211
fromcontrol.ltiimportLTI,bandwidth,damp,dcgain,evalfr,poles,zeros
1312

1413

@@ -189,6 +188,10 @@ def test_isdtime(self, objfun, arg, dt, ref, strictref):
189188
assertisctime(obj)==ref
190189
assertisctime(obj,strict=True)==strictref
191190

191+
defp(*args):
192+
# convenience for parametrize below
193+
returnpytest.param(*args,marks=pytest.mark.slycot)
194+
192195
@pytest.mark.usefixtures("editsdefaults")
193196
@pytest.mark.parametrize("fcn", [ct.ss,ct.tf,ct.frd])
194197
@pytest.mark.parametrize("nstate, nout, ninp, omega, squeeze, shape", [
@@ -201,26 +204,26 @@ def test_isdtime(self, objfun, arg, dt, ref, strictref):
201204
[3,1,1,0.1,False, (1,1)],
202205
[3,1,1, [0.1],False, (1,1,1)],
203206
[3,1,1, [0.1,1,10],False, (1,1,3)],
204-
[1,2,1,0.1,None, (2,1)],# SIMO
205-
[1,2,1, [0.1],None, (2,1,1)],
206-
[1,2,1, [0.1,1,10],None, (2,1,3)],
207-
[2,2,1,0.1,True, (2,)],
208-
[2,2,1, [0.1],True, (2,)],
209-
[3,2,1,0.1,False, (2,1)],
210-
[3,2,1, [0.1],False, (2,1,1)],
211-
[3,2,1, [0.1,1,10],False, (2,1,3)],
212-
[1,1,2, [0.1,1,10],None, (1,2,3)],# MISO
213-
[2,1,2, [0.1,1,10],True, (2,3)],
214-
[3,1,2, [0.1,1,10],False, (1,2,3)],
215-
[1,1,2,0.1,None, (1,2)],
216-
[1,1,2,0.1,True, (2,)],
217-
[1,1,2,0.1,False, (1,2)],
218-
[1,2,2, [0.1,1,10],None, (2,2,3)],# MIMO
219-
[2,2,2, [0.1,1,10],True, (2,2,3)],
220-
[3,2,2, [0.1,1,10],False, (2,2,3)],
221-
[1,2,2,0.1,None, (2,2)],
222-
[2,2,2,0.1,True, (2,2)],
223-
[3,2,2,0.1,False, (2,2)],
207+
p(1,2,1,0.1,None, (2,1)),
208+
p(1,2,1, [0.1],None, (2,1,1)),
209+
p(1,2,1, [0.1,1,10],None, (2,1,3)),
210+
p(2,2,1,0.1,True, (2,)),
211+
p(2,2,1, [0.1],True, (2,)),
212+
p(3,2,1,0.1,False, (2,1)),
213+
p(3,2,1, [0.1],False, (2,1,1)),
214+
p(3,2,1, [0.1,1,10],False, (2,1,3)),
215+
p(1,1,2, [0.1,1,10],None, (1,2,3)),# MISO
216+
p(2,1,2, [0.1,1,10],True, (2,3)),
217+
p(3,1,2, [0.1,1,10],False, (1,2,3)),
218+
p(1,1,2,0.1,None, (1,2)),
219+
p(1,1,2,0.1,True, (2,)),
220+
p(1,1,2,0.1,False, (1,2)),
221+
p(1,2,2, [0.1,1,10],None, (2,2,3)),# MIMO
222+
p(2,2,2, [0.1,1,10],True, (2,2,3)),
223+
p(3,2,2, [0.1,1,10],False, (2,2,3)),
224+
p(1,2,2,0.1,None, (2,2)),
225+
p(2,2,2,0.1,True, (2,2)),
226+
p(3,2,2,0.1,False, (2,2)),
224227
])
225228
@pytest.mark.parametrize("omega_type", ["numpy","native"])
226229
deftest_squeeze(self,fcn,nstate,nout,ninp,omega,squeeze,shape,
@@ -229,9 +232,6 @@ def test_squeeze(self, fcn, nstate, nout, ninp, omega, squeeze, shape,
229232
# Create the system to be tested
230233
iffcn==ct.frd:
231234
sys=fcn(ct.rss(nstate,nout,ninp), [1e-2,1e-1,1,1e1,1e2])
232-
eliffcn==ct.tfand (nout>1orninp>1)andnotslycot_check():
233-
pytest.skip("Conversion of MIMO systems to transfer functions "
234-
"requires slycot.")
235235
else:
236236
sys=fcn(ct.rss(nstate,nout,ninp))
237237

‎control/tests/margin_test.py‎

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
fromcontrolimportControlMIMONotImplemented,FrequencyResponseData, \
1616
StateSpace,TransferFunction,margin,phase_crossover_frequencies, \
1717
stability_margins,disk_margins,tf,ss
18-
fromcontrol.exceptionimportslycot_check
1918

2019
s=TransferFunction.s
2120

@@ -394,6 +393,7 @@ def test_siso_disk_margin():
394393
DM=disk_margins(L,omega,skew=1.0)[0]
395394
assert_allclose([DM], [SM],atol=0.01)
396395

396+
@pytest.mark.slycot
397397
deftest_mimo_disk_margin():
398398
# Frequencies of interest
399399
omega=np.logspace(-1,3,1001)
@@ -404,23 +404,32 @@ def test_mimo_disk_margin():
404404
Lo=P*K# loop transfer function, broken at plant output
405405
Li=K*P# loop transfer function, broken at plant input
406406

407-
ifslycot_check():
408-
# Balanced (S - T) disk-based stability margins at plant output
407+
# Balanced (S - T) disk-based stability margins at plant output
408+
DMo,DGMo,DPMo=disk_margins(Lo,omega,skew=0.0)
409+
assert_allclose([DMo], [0.3754],atol=0.1)# disk margin of 0.3754
410+
assert_allclose([DGMo], [3.3],atol=0.1)# disk-based gain margin of 3.3 dB
411+
assert_allclose([DPMo], [21.26],atol=0.1)# disk-based phase margin of 21.26 deg
412+
413+
# Balanced (S - T) disk-based stability margins at plant input
414+
DMi,DGMi,DPMi=disk_margins(Li,omega,skew=0.0)
415+
assert_allclose([DMi], [0.3754],atol=0.1)# disk margin of 0.3754
416+
assert_allclose([DGMi], [3.3],atol=0.1)# disk-based gain margin of 3.3 dB
417+
assert_allclose([DPMi], [21.26],atol=0.1)# disk-based phase margin of 21.26 deg
418+
419+
420+
@pytest.mark.noslycot
421+
deftest_mimo_disk_margin_exception():
422+
# Slycot not installed. Should throw exception.
423+
# Frequencies of interest
424+
omega=np.logspace(-1,3,1001)
425+
426+
# Loop transfer gain
427+
P=ss([[0,10], [-10,0]],np.eye(2), [[1,10], [-10,1]],0)# plant
428+
K=ss([], [], [], [[1,-2], [0,1]])# controller
429+
Lo=P*K# loop transfer function, broken at plant output
430+
withpytest.raises(ControlMIMONotImplemented,\
431+
match="Need slycot to compute MIMO disk_margins"):
409432
DMo,DGMo,DPMo=disk_margins(Lo,omega,skew=0.0)
410-
assert_allclose([DMo], [0.3754],atol=0.1)# disk margin of 0.3754
411-
assert_allclose([DGMo], [3.3],atol=0.1)# disk-based gain margin of 3.3 dB
412-
assert_allclose([DPMo], [21.26],atol=0.1)# disk-based phase margin of 21.26 deg
413-
414-
# Balanced (S - T) disk-based stability margins at plant input
415-
DMi,DGMi,DPMi=disk_margins(Li,omega,skew=0.0)
416-
assert_allclose([DMi], [0.3754],atol=0.1)# disk margin of 0.3754
417-
assert_allclose([DGMi], [3.3],atol=0.1)# disk-based gain margin of 3.3 dB
418-
assert_allclose([DPMi], [21.26],atol=0.1)# disk-based phase margin of 21.26 deg
419-
else:
420-
# Slycot not installed. Should throw exception.
421-
withpytest.raises(ControlMIMONotImplemented,\
422-
match="Need slycot to compute MIMO disk_margins"):
423-
DMo,DGMo,DPMo=disk_margins(Lo,omega,skew=0.0)
424433

425434
deftest_siso_disk_margin_return_all():
426435
# Frequencies of interest
@@ -439,6 +448,8 @@ def test_siso_disk_margin_return_all():
439448
assert_allclose([DPM[np.argmin(DM)]], [25.8],\
440449
atol=0.1)# disk-based phase margin of 25.8 deg
441450

451+
452+
@pytest.mark.slycot
442453
deftest_mimo_disk_margin_return_all():
443454
# Frequencies of interest
444455
omega=np.logspace(-1,3,1001)
@@ -450,29 +461,23 @@ def test_mimo_disk_margin_return_all():
450461
Lo=P*K# loop transfer function, broken at plant output
451462
Li=K*P# loop transfer function, broken at plant input
452463

453-
ifslycot_check():
454-
# Balanced (S - T) disk-based stability margins at plant output
455-
DMo,DGMo,DPMo=disk_margins(Lo,omega,skew=0.0,returnall=True)
456-
assert_allclose([omega[np.argmin(DMo)]], [omega[0]],\
457-
atol=0.01)# sensitivity peak at 0 rad/s (or smallest provided)
458-
assert_allclose([min(DMo)], [0.3754],atol=0.1)# disk margin of 0.3754
459-
assert_allclose([DGMo[np.argmin(DMo)]], [3.3],\
460-
atol=0.1)# disk-based gain margin of 3.3 dB
461-
assert_allclose([DPMo[np.argmin(DMo)]], [21.26],\
462-
atol=0.1)# disk-based phase margin of 21.26 deg
463-
464-
# Balanced (S - T) disk-based stability margins at plant input
465-
DMi,DGMi,DPMi=disk_margins(Li,omega,skew=0.0,returnall=True)
466-
assert_allclose([omega[np.argmin(DMi)]], [omega[0]],\
467-
atol=0.01)# sensitivity peak at 0 rad/s (or smallest provided)
468-
assert_allclose([min(DMi)], [0.3754],\
469-
atol=0.1)# disk margin of 0.3754
470-
assert_allclose([DGMi[np.argmin(DMi)]], [3.3],\
471-
atol=0.1)# disk-based gain margin of 3.3 dB
472-
assert_allclose([DPMi[np.argmin(DMi)]], [21.26],\
473-
atol=0.1)# disk-based phase margin of 21.26 deg
474-
else:
475-
# Slycot not installed. Should throw exception.
476-
withpytest.raises(ControlMIMONotImplemented,\
477-
match="Need slycot to compute MIMO disk_margins"):
478-
DMo,DGMo,DPMo=disk_margins(Lo,omega,skew=0.0,returnall=True)
464+
# Balanced (S - T) disk-based stability margins at plant output
465+
DMo,DGMo,DPMo=disk_margins(Lo,omega,skew=0.0,returnall=True)
466+
assert_allclose([omega[np.argmin(DMo)]], [omega[0]],\
467+
atol=0.01)# sensitivity peak at 0 rad/s (or smallest provided)
468+
assert_allclose([min(DMo)], [0.3754],atol=0.1)# disk margin of 0.3754
469+
assert_allclose([DGMo[np.argmin(DMo)]], [3.3],\
470+
atol=0.1)# disk-based gain margin of 3.3 dB
471+
assert_allclose([DPMo[np.argmin(DMo)]], [21.26],\
472+
atol=0.1)# disk-based phase margin of 21.26 deg
473+
474+
# Balanced (S - T) disk-based stability margins at plant input
475+
DMi,DGMi,DPMi=disk_margins(Li,omega,skew=0.0,returnall=True)
476+
assert_allclose([omega[np.argmin(DMi)]], [omega[0]],\
477+
atol=0.01)# sensitivity peak at 0 rad/s (or smallest provided)
478+
assert_allclose([min(DMi)], [0.3754],\
479+
atol=0.1)# disk margin of 0.3754
480+
assert_allclose([DGMi[np.argmin(DMi)]], [3.3],\
481+
atol=0.1)# disk-based gain margin of 3.3 dB
482+
assert_allclose([DPMi[np.argmin(DMi)]], [21.26],\
483+
atol=0.1)# disk-based phase margin of 21.26 deg

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp