Move _tf_close_coeff back to testing realm and make better use of assertion messages by bnavigator · Pull Request #1109 · python-control/python-control
Before:
___________________________ TestStateSpace.test_pow ____________________________ self = <control.tests.statesp_test.TestStateSpace object at 0x108ea1580> sys222 = StateSpace( array([[ 4., 1.], [ 2., -3.]]), array([[ 5., 2.], [-3., -3.]]), array([[ 2., -4.], [ 0., 1.]]), array([[ 3., 2.], [ 1., -1.]]), states=2, outputs=2, inputs=2) sys322 = StateSpace( array([[-3., 4., 2.], [-1., -3., 0.], [ 2., 5., 3.]]), array([[ 1., 4.], [-3., ..., -3.], [ 1., 4., 3.]]), array([[-2., 4.], [ 0., 1.]]), name='sys322', states=3, outputs=2, inputs=2) @slycotonly def test_pow(self, sys222, sys322): """Test state space powers.""" for sys in [sys222, sys322]: # Power of 0 result = sys**0 expected = StateSpace([], [], [], np.eye(2), dt=0) np.testing.assert_allclose(expected.A, result.A) np.testing.assert_allclose(expected.B, result.B) np.testing.assert_allclose(expected.C, result.C) np.testing.assert_allclose(expected.D, result.D) # Power of 1 result = sys**1 expected = sys np.testing.assert_allclose(expected.A, result.A) np.testing.assert_allclose(expected.B, result.B) np.testing.assert_allclose(expected.C, result.C) np.testing.assert_allclose(expected.D, result.D) # Power of -1 (inverse of biproper system) # Testing transfer function representations to avoid the # non-uniqueness of the state-space representation. Once MIMO # canonical forms are supported, can check canonical state-space # matrices instead. result = (sys * sys**-1).minreal() expected = StateSpace([], [], [], np.eye(2), dt=0) assert _tf_close_coeff( ss2tf(expected).minreal(), ss2tf(result).minreal(), ) result = (sys**-1 * sys).minreal() expected = StateSpace([], [], [], np.eye(2), dt=0) > assert _tf_close_coeff( ss2tf(expected).minreal(), ss2tf(result).minreal(), ) E assert False E + where False = _tf_close_coeff(TransferFunction(\n[[array([1.]), array([0.])],\n [array([0.]), array([1.])]],\n[[array([1.]), array([1.])],\n [array([1.]), array([1.])]],\noutputs=2, inputs=2), TransferFunction(\n[[array([1.]), array([-2.76395297e-15, -1.35541257e-13, 9.01576541e-13])],\n [array([0.]), array([1.])]],\n[[array([1.]), array([ 1., 3., -9., -41.])],\n [array([1.]), array([1.])]],\noutputs=2, inputs=2)) E + where TransferFunction(\n[[array([1.]), array([0.])],\n [array([0.]), array([1.])]],\n[[array([1.]), array([1.])],\n [array([1.]), array([1.])]],\noutputs=2, inputs=2) = minreal() E + where minreal = TransferFunction(\n[[array([1.]), array([0.])],\n [array([0.]), array([1.])]],\n[[array([1.]), array([1.])],\n [array([1.]), array([1.])]],\noutputs=2, inputs=2).minreal E + where TransferFunction(\n[[array([1.]), array([0.])],\n [array([0.]), array([1.])]],\n[[array([1.]), array([1.])],\n [array([1.]), array([1.])]],\noutputs=2, inputs=2) = ss2tf(StateSpace(\narray([], shape=(0, 0), dtype=float64),\narray([], shape=(0, 2), dtype=float64),\narray([], shape=(2, 0), dtype=float64),\narray([[1., 0.],\n [0., 1.]]),\nstates=0, outputs=2, inputs=2)) E + and TransferFunction(\n[[array([1.]), array([-2.76395297e-15, -1.35541257e-13, 9.01576541e-13])],\n [array([0.]), array([1.])]],\n[[array([1.]), array([ 1., 3., -9., -41.])],\n [array([1.]), array([1.])]],\noutputs=2, inputs=2) = minreal() E + where minreal = TransferFunction(\n[[array([ 1., 3., -9., -41.]), \n array([-2.76395297e-15, -1.35541257e-13, 9.01576541e-13])],\n ...., 3., -9., -41.]), array([ 1., 3., -9., -41.])],\n [array([1.]), array([1., 0., 0., 0.])]],\noutputs=2, inputs=2).minreal E + where TransferFunction(\n[[array([ 1., 3., -9., -41.]), \n array([-2.76395297e-15, -1.35541257e-13, 9.01576541e-13])],\n ...., 3., -9., -41.]), array([ 1., 3., -9., -41.])],\n [array([1.]), array([1., 0., 0., 0.])]],\noutputs=2, inputs=2) = ss2tf(StateSpace(\narray([[ 4.86563613, -0.22114886, -14.38268526],\n [ 3.86388385, -1.64824725, -16.2652334 ],\n ... [0.00000000e+00, 2.59786829e-16, 3.85014366e-15]]),\narray([[1., 0.],\n [0., 1.]]),\nstates=3, outputs=2, inputs=2)) control/tests/statesp_test.py:596: AssertionError
After:
________________ TestStateSpace.test_pow_inv[sys322-inv*sys] __________________ self = <control.tests.statesp_test.TestStateSpace object at 0x10b398260> request = <FixtureRequest for <Function test_pow_inv[sys322-inv*sys]>> sysname = 'sys322', order = 'inv*sys' @slycotonly @pytest.mark.parametrize("order", ["inv*sys", "sys*inv"]) @pytest.mark.parametrize("sysname", ["sys222", "sys322"]) def test_pow_inv(self, request, sysname, order): """Power of -1 (inverse of biproper system). Testing transfer function representations to avoid the non-uniqueness of the state-space representation. Once MIMO canonical forms are supported, can check canonical state-space matrices instead. """ sys = request.getfixturevalue(sysname) if order == "inv*sys": result = (sys**-1 * sys).minreal() else: result = (sys * sys**-1).minreal() expected = StateSpace([], [], [], np.eye(2), dt=0) > assert_tf_close_coeff( ss2tf(expected).minreal(), ss2tf(result).minreal()) control/tests/statesp_test.py:601: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tf_a = TransferFunction( [[array([1.]), array([0.])], [array([0.]), array([1.])]], [[array([1.]), array([1.])], [array([1.]), array([1.])]], outputs=2, inputs=2) tf_b = TransferFunction( [[array([1.]), array([-2.76395297e-15, -1.35541257e-13, 9.01576541e-13])], [array([0.]), array([1.])]], [[array([1.]), array([ 1., 3., -9., -41.])], [array([1.]), array([1.])]], outputs=2, inputs=2) rtol = 1e-05, atol = 1e-08 def assert_tf_close_coeff(tf_a, tf_b, rtol=1e-5, atol=1e-8): """Check if two transfer functions have close coefficients. Parameters ---------- tf_a : TransferFunction First transfer function. tf_b : TransferFunction Second transfer function. rtol : float Relative tolerance for ``np.testing.assert_allclose``. atol : float Absolute tolerance for ``np.testing.assert_allclose``. Raises ------ AssertionError """ # Check number of outputs and inputs assert tf_a.noutputs == tf_b.noutputs assert tf_a.ninputs == tf_b.ninputs # Check timestep assert tf_a.dt == tf_b.dt # Check coefficient arrays for i in range(tf_a.noutputs): for j in range(tf_a.ninputs): > np.testing.assert_allclose( tf_a.num[i][j], tf_b.num[i][j], rtol=rtol, atol=atol) E AssertionError: E Not equal to tolerance rtol=1e-05, atol=1e-08 E E (shapes (1,), (3,) mismatch) E ACTUAL: array([0.]) E DESIRED: array([-2.763953e-15, -1.355413e-13, 9.015765e-13])