33RMM, 30 Mar 2011 (based on TestModelSimp from v0.4a)
44"""
55
6+ import math
67import warnings
78
89import numpy as np
@@ -45,7 +46,7 @@ def testMarkovSignature(self):
4546 inputs = U ,
4647 input_labels = 'u' ,
4748 )
48-
49+
4950 # setup
5051 m = 3
5152 Htrue = np .array ([1. , 0. , 0. ])
@@ -104,7 +105,6 @@ def testMarkovSignature(self):
104105 HT = markov (response , m )
105106 np .testing .assert_array_almost_equal (HT , np .transpose (Htrue ))
106107 response .transpose = False
107-
108108
109109 # Test example from docstring
110110 # TODO: There is a problem here, last markov parameter does not fit
@@ -215,7 +215,7 @@ def testMarkovResults(self, k, m, n):
215215 Mtrue = np .hstack ([Hd .D ] + [
216216 Hd .C @ np .linalg .matrix_power (Hd .A , i ) @ Hd .B
217217 for i in range (m - 1 )])
218-
218+
219219 Mtrue = np .squeeze (Mtrue )
220220
221221 # Generate input/output data
@@ -241,8 +241,8 @@ def testMarkovResults(self, k, m, n):
241241 Mcomp_scaled = markov (response , m , dt = Ts )
242242
243243 np .testing .assert_allclose (Mtrue , Mcomp , rtol = 1e-6 , atol = 1e-8 )
244- np .testing .assert_allclose (Mtrue_scaled , Mcomp_scaled , rtol = 1e-6 , atol = 1e-8 )
245-
244+ np .testing .assert_allclose (
245+ Mtrue_scaled , Mcomp_scaled , rtol = 1e-6 , atol = 1e-8 )
246246
247247 def testERASignature (self ):
248248
@@ -256,7 +256,7 @@ def testERASignature(self):
256256 B = np .array ([[1. ],[1. ,]])
257257 C = np .array ([[1. , 0. ,]])
258258 D = np .array ([[0. ,]])
259-
259+
260260 T = np .arange (0 ,10 ,1 )
261261 sysd_true = StateSpace (A ,B ,C ,D ,True )
262262 ir_true = impulse_response (sysd_true ,T = T )
@@ -265,15 +265,15 @@ def testERASignature(self):
265265 sysd_est , _ = eigensys_realization (ir_true ,r = 2 )
266266 ir_est = impulse_response (sysd_est , T = T )
267267 _ , H_est = ir_est
268-
268+
269269 np .testing .assert_allclose (H_true , H_est , rtol = 1e-6 , atol = 1e-8 )
270270
271271 # test ndarray
272272 _ , YY_true = ir_true
273273 sysd_est , _ = eigensys_realization (YY_true ,r = 2 )
274274 ir_est = impulse_response (sysd_est , T = T )
275275 _ , H_est = ir_est
276-
276+
277277 np .testing .assert_allclose (H_true , H_est , rtol = 1e-6 , atol = 1e-8 )
278278
279279 # test mimo
@@ -307,18 +307,18 @@ def testERASignature(self):
307307 step_true = step_response (sysd_true )
308308 step_est = step_response (sysd_est )
309309
310- np .testing .assert_allclose (step_true .outputs ,
310+ np .testing .assert_allclose (step_true .outputs ,
311311 step_est .outputs ,
312312 rtol = 1e-6 , atol = 1e-8 )
313-
313+
314314 # test ndarray
315315 _ , YY_true = ir_true
316316 sysd_est , _ = eigensys_realization (YY_true ,r = 4 ,dt = dt )
317317
318318 step_true = step_response (sysd_true , T = T )
319319 step_est = step_response (sysd_est , T = T )
320320
321- np .testing .assert_allclose (step_true .outputs ,
321+ np .testing .assert_allclose (step_true .outputs ,
322322 step_est .outputs ,
323323 rtol = 1e-6 , atol = 1e-8 )
324324
@@ -403,7 +403,7 @@ def testBalredTruncate(self):
403403 B = np .array ([[2. ], [0. ], [0. ], [0. ]])
404404 C = np .array ([[0.5 , 0.6875 , 0.7031 , 0.5 ]])
405405 D = np .array ([[0. ]])
406-
406+
407407 sys = StateSpace (A , B , C , D )
408408 orders = 2
409409 rsys = balred (sys , orders , method = 'truncate' )
@@ -424,7 +424,7 @@ def testBalredTruncate(self):
424424 # Apply a similarity transformation
425425 Ar , Br , Cr = T @ Ar @ T , T @ Br , Cr @ T
426426 break
427-
427+
428428 # Make sure we got the correct answer
429429 np .testing .assert_array_almost_equal (Ar , Artrue , decimal = 2 )
430430 np .testing .assert_array_almost_equal (Br , Brtrue , decimal = 4 )
@@ -444,20 +444,20 @@ def testBalredMatchDC(self):
444444 B = np .array ([[2. ], [0. ], [0. ], [0. ]])
445445 C = np .array ([[0.5 , 0.6875 , 0.7031 , 0.5 ]])
446446 D = np .array ([[0. ]])
447-
447+
448448 sys = StateSpace (A , B , C , D )
449449 orders = 2
450450 rsys = balred (sys ,orders ,method = 'matchdc' )
451451 Ar , Br , Cr , Dr = rsys .A , rsys .B , rsys .C , rsys .D
452-
452+
453453 # Result from MATLAB
454454 Artrue = np .array (
455455 [[- 4.43094773 , - 4.55232904 ],
456456 [- 4.55232904 , - 5.36195206 ]])
457457 Brtrue = np .array ([[1.36235673 ], [1.03114388 ]])
458458 Crtrue = np .array ([[1.36235673 , 1.03114388 ]])
459459 Drtrue = np .array ([[- 0.08383902 ]])
460-
460+
461461 # Look for possible changes in state in slycot
462462 T1 = np .array ([[1 , 0 ], [0 , - 1 ]])
463463 T2 = np .array ([[- 1 , 0 ], [0 , 1 ]])
@@ -467,9 +467,44 @@ def testBalredMatchDC(self):
467467 # Apply a similarity transformation
468468 Ar , Br , Cr = T @ Ar @ T , T @ Br , Cr @ T
469469 break
470-
470+
471471 # Make sure we got the correct answer
472472 np .testing .assert_array_almost_equal (Ar , Artrue , decimal = 2 )
473473 np .testing .assert_array_almost_equal (Br , Brtrue , decimal = 4 )
474474 np .testing .assert_array_almost_equal (Cr , Crtrue , decimal = 4 )
475475 np .testing .assert_array_almost_equal (Dr , Drtrue , decimal = 4 )
476+
477+
478+ @pytest .mark .parametrize ("kwargs, nstates, noutputs, ninputs" , [
479+ ({'elim_states' : [1 , 3 ]}, 3 , 3 , 3 ),
480+ ({'elim_inputs' : [1 , 2 ], 'keep_states' : [1 , 3 ]}, 2 , 3 , 1 ),
481+ ({'elim_outputs' : [1 , 2 ], 'keep_inputs' : [0 , 1 ],}, 5 , 1 , 2 ),
482+ ({'keep_states' : [2 , 0 ], 'keep_outputs' : [0 , 1 ]}, 2 , 2 , 3 ),
483+ ({'elim_inputs' : [0 , 1 , 2 ]}, 5 , 3 , 0 ), # no inputs
484+ ({'elim_outputs' : [0 , 1 , 2 ]}, 5 , 0 , 3 ), # no outputs
485+ ({'elim_states' : [0 , 1 , 2 , 3 , 4 ]}, 0 , 3 , 3 ), # no states
486+ ({'elim_states' : [0 , 1 ], 'keep_states' : [1 , 2 ]}, None , None , None )
487+ ])
488+ @pytest .mark .parametrize ("method" , ['truncate' , 'matchdc' ])
489+ def test_model_reduction (method , kwargs , nstates , noutputs , ninputs ):
490+ sys = ct .rss (5 , 3 , 3 )
491+
492+ if nstates is None :
493+ # Arguments should generate an error
494+ with pytest .raises (ValueError , match = "can't provide both" ):
495+ red = ct .model_reduction (sys , ** kwargs , method = method )
496+ return
497+ else :
498+ red = ct .model_reduction (sys , ** kwargs , method = method )
499+
500+ assert red .nstates == nstates
501+ assert red .ninputs == ninputs
502+ assert red .noutputs == noutputs
503+
504+ if method == 'matchdc' :
505+ # Define a new system with truncated inputs and outputs
506+ # (assumes we always keep the initial inputs and outputs)
507+ chk = ct .ss (
508+ sys .A , sys .B [:, :ninputs ], sys .C [:noutputs , :],
509+ sys .D [:noutputs , :][:, :ninputs ])
510+ np .testing .assert_allclose (red (0 ), chk (0 ))
0 commit comments