|
1 | | -"""statesp_test.py - test state space class |
| 1 | +"""Tests for the StateSpace class. |
2 | 2 |
|
3 | 3 | RMM, 30 Mar 2011 based on TestStateSp from v0.4a) |
4 | 4 | RMM, 14 Jun 2019 statesp_array_test.py coverted from statesp_test.py to test |
@@ -560,54 +560,44 @@ def test_rmul_mimo_siso(self, left, right, expected): |
560 | 560 | ) |
561 | 561 |
|
562 | 562 | @slycotonly |
563 | | - def test_pow(self, sys222, sys322): |
| 563 | + @pytest.mark.parametrize("power", [0, 1, 3, -3]) |
| 564 | + @pytest.mark.parametrize("sysname", ["sys222", "sys322"]) |
| 565 | + def test_pow(self, request, sysname, power): |
564 | 566 | """Test state space powers.""" |
565 | | - for sys in [sys222, sys322]: |
566 | | - # Power of 0 |
567 | | - result = sys**0 |
568 | | - expected = StateSpace([], [], [], np.eye(2), dt=0) |
569 | | - np.testing.assert_allclose(expected.A, result.A) |
570 | | - np.testing.assert_allclose(expected.B, result.B) |
571 | | - np.testing.assert_allclose(expected.C, result.C) |
572 | | - np.testing.assert_allclose(expected.D, result.D) |
573 | | - # Power of 1 |
574 | | - result = sys**1 |
575 | | - expected = sys |
576 | | - np.testing.assert_allclose(expected.A, result.A) |
577 | | - np.testing.assert_allclose(expected.B, result.B) |
578 | | - np.testing.assert_allclose(expected.C, result.C) |
579 | | - np.testing.assert_allclose(expected.D, result.D) |
580 | | - # Power of -1 (inverse of biproper system) |
581 | | - # Testing transfer function representations to avoid the |
582 | | - # non-uniqueness of the state-space representation. Once MIMO |
583 | | - # canonical forms are supported, can check canonical state-space |
584 | | - # matrices instead. |
585 | | - result = (sys * sys**-1).minreal() |
586 | | - expected = StateSpace([], [], [], np.eye(2), dt=0) |
587 | | - assert_tf_close_coeff( |
588 | | - ss2tf(expected).minreal(), |
589 | | - ss2tf(result).minreal(), |
590 | | - ) |
| 567 | + sys = request.getfixturevalue(sysname) |
| 568 | + result = sys**power |
| 569 | + if power == 0: |
| 570 | + expected = StateSpace([], [], [], np.eye(sys.ninputs), dt=0) |
| 571 | + else: |
| 572 | + sign = 1 if power > 0 else -1 |
| 573 | + expected = sys**sign |
| 574 | + for i in range(1,abs(power)): |
| 575 | + expected *= sys**sign |
| 576 | + np.testing.assert_allclose(expected.A, result.A) |
| 577 | + np.testing.assert_allclose(expected.B, result.B) |
| 578 | + np.testing.assert_allclose(expected.C, result.C) |
| 579 | + np.testing.assert_allclose(expected.D, result.D) |
| 580 | + |
| 581 | + @slycotonly |
| 582 | + @pytest.mark.parametrize("order", ["inv*sys", "sys*inv"]) |
| 583 | + @pytest.mark.parametrize("sysname", ["sys222", "sys322"]) |
| 584 | + def test_pow_inv(self, request, sysname, order): |
| 585 | + """Power of -1 (inverse of biproper system). |
| 586 | +
|
| 587 | + Testing transfer function representations to avoid the |
| 588 | + non-uniqueness of the state-space representation. Once MIMO |
| 589 | + canonical forms are supported, can check canonical state-space |
| 590 | + matrices instead. |
| 591 | + """ |
| 592 | + sys = request.getfixturevalue(sysname) |
| 593 | + if order == "inv*sys": |
591 | 594 | result = (sys**-1 * sys).minreal() |
592 | | - expected = StateSpace([], [], [], np.eye(2), dt=0) |
593 | | - assert_tf_close_coeff( |
594 | | - ss2tf(expected).minreal(), |
595 | | - ss2tf(result).minreal(), |
596 | | - ) |
597 | | - # Power of 3 |
598 | | - result = sys**3 |
599 | | - expected = sys * sys * sys |
600 | | - np.testing.assert_allclose(expected.A, result.A) |
601 | | - np.testing.assert_allclose(expected.B, result.B) |
602 | | - np.testing.assert_allclose(expected.C, result.C) |
603 | | - np.testing.assert_allclose(expected.D, result.D) |
604 | | - # Power of -3 |
605 | | - result = sys**-3 |
606 | | - expected = sys**-1 * sys**-1 * sys**-1 |
607 | | - np.testing.assert_allclose(expected.A, result.A) |
608 | | - np.testing.assert_allclose(expected.B, result.B) |
609 | | - np.testing.assert_allclose(expected.C, result.C) |
610 | | - np.testing.assert_allclose(expected.D, result.D) |
| 595 | + else: |
| 596 | + result = (sys * sys**-1).minreal() |
| 597 | + expected = StateSpace([], [], [], np.eye(sys.ninputs), dt=0) |
| 598 | + assert_tf_close_coeff( |
| 599 | + ss2tf(expected).minreal(), |
| 600 | + ss2tf(result).minreal()) |
611 | 601 |
|
612 | 602 | @slycotonly |
613 | 603 | def test_truediv(self, sys222, sys322): |
|
0 commit comments