Hello community, here is the log from the commit of package python-slycot for openSUSE:Factory checked in at 2019-11-09 23:39:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-slycot (Old) and /work/SRC/openSUSE:Factory/.python-slycot.new.2990 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-slycot" Sat Nov 9 23:39:46 2019 rev:5 rq:746657 version:0.3.5.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-slycot/python-slycot.changes 2019-09-23 12:46:29.233520431 +0200 +++ /work/SRC/openSUSE:Factory/.python-slycot.new.2990/python-slycot.changes 2019-11-09 23:39:47.457241774 +0100 @@ -1,0 +2,7 @@ +Fri Nov 8 13:30:41 UTC 2019 - Benjamin Greiner <[email protected]> + +- fix unittests to pass on all architectures + * fix-test-sg03ad.patch see upstream PR#82 + * fix-test-td04ad.patch see upstream PR#83 + +------------------------------------------------------------------- New: ---- fix-test-sg03ad.patch fix-test-td04ad.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-slycot.spec ++++++ --- /var/tmp/diff_new_pack.q02ZW9/_old 2019-11-09 23:39:47.949242531 +0100 +++ /var/tmp/diff_new_pack.q02ZW9/_new 2019-11-09 23:39:47.949242531 +0100 @@ -25,6 +25,8 @@ Group: Development/Languages/Python URL: https://github.com/python-control/Slycot Source: https://files.pythonhosted.org/packages/source/s/slycot/slycot-%{version}.tar.gz +Patch0: fix-test-td04ad.patch +Patch1: fix-test-sg03ad.patch BuildRequires: %{python_module coverage} BuildRequires: %{python_module devel} BuildRequires: %{python_module nose} @@ -49,6 +51,8 @@ %prep %setup -q -n slycot-%{version} +%patch0 -p1 +%patch1 -p1 %build export CFLAGS="%{optflags}" ++++++ fix-test-sg03ad.patch ++++++ diff --git a/slycot/tests/test_sg03ad.py b/slycot/tests/test_sg03ad.py index 7b498d6..bc4b043 100644 --- a/slycot/tests/test_sg03ad.py +++ b/slycot/tests/test_sg03ad.py @@ -8,52 +8,50 @@ import unittest from slycot import synthesis import numpy as np -from numpy.testing import assert_raises, assert_almost_equal +from numpy.testing import assert_almost_equal # test cases from # http://www.qucosa.de/fileadmin/data/qucosa/documents/4168/data/b002.pdf + class test_sg03ad(unittest.TestCase): def test_sg03ad_a(self): # Example 1 n = 100 - Xref = np.ones((n,n)) + Xref = np.ones((n, n)) U = np.tril(Xref) for t in range(0, 50, 10): - A = 2.0**(-t) - np.eye(n) + np.diag(range(1,n+1)) + U.T - E = np.eye(n) + 2**(-t)*U + A = 2.0**(-t) - np.eye(n) + np.diag(np.arange(1, n+1)) + U.T + E = np.eye(n) + 2.0**(-t)*U Y = A.T.dot(Xref).dot(E) + E.T.dot(Xref).dot(A) - Q = np.zeros((n,n)) - Z = np.zeros((n,n)) + Q = np.zeros((n, n)) + Z = np.zeros((n, n)) A, E, Q, Z, X, scale, sep, ferr, alphar, alphai, beta = \ synthesis.sg03ad('C', 'B', 'N', 'N', 'L', n, A, E, Q, Z, Y) assert_almost_equal(Xref, X) - + def test_sg03ad_3(self): n = 3 A = np.array([[3.0, 1.0, 1.0], [1.0, 3.0, 0.0], [1.0, 0.0, 2.0]]) E = np.array([[1.0, 3.0, 0.0], - [3.0, 2.0, 1.0], - [1.0, 0.0, 1.0]]) + [3.0, 2.0, 1.0], + [1.0, 0.0, 1.0]]) Y = np.array([[64.0, 73.0, 28.0], - [73.0, 70.0, 25.0], - [28.0, 25.0, 18.0]]) + [73.0, 70.0, 25.0], + [28.0, 25.0, 18.0]]) Xref = np.array([[-2.0000, -1.0000, 0.0000], - [-1.0000, -3.0000, -1.0000], - [0.0000, -1.0000, -3.0000]]) - Q = np.zeros((3,3)) - Z = np.zeros((3,3)) + [-1.0000, -3.0000, -1.0000], + [0.0000, -1.0000, -3.0000]]) + Q = np.zeros((3, 3)) + Z = np.zeros((3, 3)) A, E, Q, Z, X, scale, sep, ferr, alphar, alphai, beta = \ synthesis.sg03ad('C', 'B', 'N', 'N', 'L', n, A, E, Q, Z, -Y) - #print(A, E, Q, Z, X, scale, sep) + # print(A, E, Q, Z, X, scale, sep) assert_almost_equal(X, Xref) -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(TestConvert) - if __name__ == "__main__": unittest.main() ++++++ fix-test-td04ad.patch ++++++ diff --git a/slycot/tests/test.py b/slycot/tests/test.py index ec0b072..eca7b38 100644 --- a/slycot/tests/test.py +++ b/slycot/tests/test.py @@ -49,24 +49,6 @@ class Test(unittest.TestCase): self.assertAlmostEqual(Ac[1][0], 1) self.assertAlmostEqual(Ac[1][1], -3) - def test_td04ad_static(self): - """Regression: td04ad (TFM -> SS transformation) for static TFM""" - import numpy as np - from itertools import product - # 'C' fails on static TFs - for nout,nin,rc in product(range(1,6),range(1,6),['R']): - num = np.reshape(np.arange(nout*nin),(nout,nin,1)) - if rc == 'R': - den = np.reshape(np.arange(1,1+nout),(nout,1)) - else: - den = np.reshape(np.arange(1,1+nin),(nin,1)) - index = np.tile([0],den.shape[0]) - nr,a,b,c,d = transform.td04ad(rc,nin,nout,index,den,num) - - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(TestConvert) - if __name__ == "__main__": unittest.main() diff --git a/slycot/tests/test_td04ad.py b/slycot/tests/test_td04ad.py index ab2aa3e..e442a96 100644 --- a/slycot/tests/test_td04ad.py +++ b/slycot/tests/test_td04ad.py @@ -3,19 +3,18 @@ # test_td04ad.py - test suite for tf -> ss conversion # RvP, 04 Jun 2018 -from __future__ import print_function +from __future__ import print_function, division import unittest from slycot import transform import numpy as np -from numpy.testing import assert_raises, assert_almost_equal class TestTf2SS(unittest.TestCase): - def test_td04ad_case1(self): - """td04ad: Convert with both 'C' and 'R' options""" - + def test_td04ad_c(self): + """td04ad: Convert with 'C' option""" + # for octave: """ num = { [0.0, 0.0, 1.0 ], [ 1.0, 0.0 ]; @@ -25,45 +24,96 @@ class TestTf2SS(unittest.TestCase): [1.0, 0.4, 3.0], [ 1.0, 1.0 ]; [1.0, 0.4, 3.0], [ 1.0, 1.0 ]}; """ - - # common denominators for the inputs - n = 2 + m = 2 p = 3 + d = 3 num = np.array([ - [ [0.0, 0.0, 1.0 ], [ 1.0, 0.0, 0.0 ] ], - [ [3.0, -1.0, 1.0 ], [ 0.0, 1.0, 0.0 ] ], - [ [0.0, 0.0, 1.0], [ 0.0, 2.0, 0.0 ] ] ]) - p, m, d = num.shape + [ [0.0, 0.0, 1.0], [1.0, 0.0, 0.0] ], + [ [3.0, -1.0, 1.0], [0.0, 1.0, 0.0] ], + [ [0.0, 0.0, 1.0], [0.0, 2.0, 0.0] ] ]) + numc = np.zeros((max(1, m, p), max(1, m, p), d), dtype=float) numc[:p,:m,:] = num - denc = np.array( [ [1.0, 0.4, 3.0], [ 1.0, 1.0, 0.0 ] ]) indc = np.array( [ 2, 1 ], dtype=int) - denr = np.array( - [ [1.0, 0.4, 3.0], [ 1.0, 1.0, 0.0 ], [1.0, 0.0, 0.0] ]) - indr = np.array( - [ 2, 1, 0 ], dtype=int) - n, A, B, C, D = transform.td04ad('C', 2, 3, indc, denc, numc) + nref = 3 + Aref = np.array([ [-1, 0, 0], + [ 0, -0.4, -0.3], + [ 0, 10, 0] ]) + Bref = np.array([ [0, -1], + [1, 0], + [0, 0] ]) + Cref = np.array([ [1, 0, 0.1], + [-1, -2.2, -0.8], + [-2, 0, 0.1] ]) + Dref = np.array([ [0, 1], + [3, 0], + [0, 0] ]) + + nr, A, B, C, D = transform.td04ad('C', m, p, indc, denc, numc) #print('A=\n', A, '\nB=\n', B, '\nC=\n', C, '\nD=\n', D) - Ac = [ [-1, 0, 0], [ 0, -0.4, -0.3], [ 0, 10, 0]] - Bc = [ [0, -1] ,[ 1 , 0], [ 0, 0]] - Cc = [ [1, 0, 0.1], [-1, -2.2, -0.8], [ -2, 0, 0.1] ] - Dc = [ [0, 1], [ 3, 0], [ 0, 0]] - np.testing.assert_array_almost_equal(A, Ac) - np.testing.assert_array_almost_equal(B, Bc) - np.testing.assert_array_almost_equal(C, Cc) - np.testing.assert_array_almost_equal(D, Dc) + np.testing.assert_equal(nref, nr) + # the returned state space representation is not guaranteed to + # be of one form for all architectures, so we transform back + # to tf and check for equality then + _, _, _, _, _, dcoeff, ucoeff = transform.tb04ad( + nr, m, p, A, B, C, D) + _, _, _, _, _, dcoeffref, ucoeffref = transform.tb04ad( + nref, m, p, Aref, Bref, Cref, Dref) + np.testing.assert_array_almost_equal(dcoeff,dcoeffref) + np.testing.assert_array_almost_equal(ucoeff,ucoeffref) + + + def test_td04ad_r(self): + """td04ad: Convert with 'R' option""" - resr = transform.td04ad('R', 2, 3, indr, denr, num) + """ example program from + http://slicot.org/objects/software/shared/doc/TD04AD.html""" + + m = 2 + p = 2 + rowcol = 'R' + index = [3, 3] + dcoeff = np.array([ [1.0, 6.0, 11.0, 6.0], [1.0, 6.0, 11.0, 6.0] ]) + + ucoeff = np.array([ [[1.0, 6.0, 12.0, 7.0], [0.0, 1.0, 4.0, 3.0]], + [[0.0, 0.0, 1.0, 1.0], [1.0, 8.0, 20.0, 15.0]] ]) + + nref = 3 + + Aref = np.array([ [ 0.5000, -0.8028, 0.9387], + [ 4.4047, -2.3380, 2.5076], + [-5.5541, 1.6872, -4.1620] ]) + Bref = np.array([ [-0.2000, -1.2500], + [ 0.0000, -0.6097], + [ 0.0000, 2.2217] ]) + Cref = np.array([ [0.0000, -0.8679, 0.2119], + [0.0000, 0.0000, 0.9002] ]) + Dref = np.array([ [1.0000, 0.0000], + [0.0000, 1.0000] ]) + + nr, A, B, C, D = transform.td04ad(rowcol, m, p, index, dcoeff, ucoeff) #print('A=\n', A, '\nB=\n', B, '\nC=\n', C, '\nD=\n', D) + np.testing.assert_equal(nref, nr) + # order of states is not guaranteed, so we reorder the reference + rindex = np.flip(np.argsort(np.diag(A))) + Arref = Aref[rindex, :][:, rindex] + Brref = Bref[rindex, :] + Crref = Cref[:, rindex] + Drref = Dref + np.testing.assert_array_almost_equal(A, Arref,decimal=4) + np.testing.assert_array_almost_equal(B, Brref,decimal=4) + np.testing.assert_array_almost_equal(C, Crref,decimal=4) + np.testing.assert_array_almost_equal(D, Drref,decimal=4) + def test_staticgain(self): """td04ad: Convert a transferfunction to SS with only static gain""" - + # 2 inputs, 3 outputs? columns share a denominator num = np.array([ [ [1.0], [2.0] ], [ [0.2], [4.3] ], @@ -71,12 +121,12 @@ class TestTf2SS(unittest.TestCase): p, m, d = num.shape numc = np.zeros((max(1, m, p), max(1, m, p), d), dtype=float) numc[:p,:m,:] = num - + # denc, columns share a common denominator denc = np.array([ [ 1.0], [0.5] ]) Dc = (num / denc).reshape((3,2)) idxc = np.zeros((2,), dtype=int) - + # denr, rows share a common denominator denr = np.array([ [1.0], [0.5], [3.0] ]) idxr = np.zeros((3,), dtype=int) @@ -84,21 +134,45 @@ class TestTf2SS(unittest.TestCase): # fails with: # On entry to TB01XD parameter number 5 had an illegal value - + n, A, B, C, D = transform.td04ad('C', 2, 3, idxc, denc, numc) #print('A=\n', A, '\nB=\n', B, '\nC=\n', C, '\nD=\n', D) self.assertEqual(A.shape, (0,0)) self.assertEqual(B.shape, (0,2)) self.assertEqual(C.shape, (3,0)) np.testing.assert_array_almost_equal(D, Dc) - + n, A, B, C, D = transform.td04ad('R', 2, 3, idxr, denr, num) #print('A=\n', A, '\nB=\n', B, '\nC=\n', C, '\nD=\n', D) self.assertEqual(A.shape, (0,0)) self.assertEqual(B.shape, (0,2)) self.assertEqual(C.shape, (3,0)) np.testing.assert_array_almost_equal(D, Dr) - + + def test_td04ad_static(self): + """Regression: td04ad (TFM -> SS transformation) for static TFM""" + from itertools import product + for nout, nin, rc in product(range(1, 6), range(1, 6), ['R', 'C']): + Dref = np.zeros((nout, nin)) + if rc == 'R': + num = np.reshape(np.arange(nout * nin), (nout, nin, 1)) + den = np.reshape(np.arange(1, 1 + nout), (nout, 1)) + index = np.repeat(0, nout) + Dref = num[:nout, :nin, 0] / np.broadcast_to(den, (nout, nin)) + else: + maxn = max(nout, nin) + num = np.zeros((maxn, maxn, 1)) + num[:nout, :nin, 0] = np.reshape( + np.arange(nout * nin), (nout, nin)) + den = np.reshape(np.arange(1, 1 + nin), (nin, 1)) + index = np.repeat(0, nin) + Dref = num[:nout, :nin, 0] / np.broadcast_to(den.T, (nout, nin)) + nr, A, B, C, D = transform.td04ad(rc, nin, nout, index, den, num) + np.testing.assert_equal(nr, 0) + for M in [A, B, C]: + np.testing.assert_equal(M, np.zeros_like(M)) + np.testing.assert_almost_equal(D, Dref) + def test_mixfeedthrough(self): """Test case popping up from control testing""" @@ -113,7 +187,7 @@ class TestTf2SS(unittest.TestCase): idxc = np.array([ 1, 0 ]) n, A, B, C, D = transform.td04ad('C', 2, 2, idxc, denc, numc) np.testing.assert_array_almost_equal(D, np.array([[0, 0],[-0.1, 0]])) - + def test_toandfrom(self): A = np.array([[-3.0]]) @@ -131,7 +205,7 @@ class TestTf2SS(unittest.TestCase): np.testing.assert_array_almost_equal(A, At) def test_tfm2ss_6(self): - """Python version of Fortran test program from + """Python version of Fortran test program from -- Bug in TD04AD when ROWCOL='C' #6 This bug was fixed in PR #27""" m = 1 @@ -145,10 +219,6 @@ class TestTf2SS(unittest.TestCase): n, A, B, C, D = transform.td04ad('C', m, p, index, dcoeff, ucoeff) self.assertEqual(n, 0) np.testing.assert_array_almost_equal(D, np.array([[64]])) - -def suite(): - return unittest.TestLoader().loadTestsFromTestCase(TestTF2SS) - if __name__ == "__main__": unittest.main() diff --git a/slycot/transform.py b/slycot/transform.py index 77b3171..f79e0ca 100644 --- a/slycot/transform.py +++ b/slycot/transform.py @@ -288,9 +288,9 @@ def tb04ad(n,m,p,A,B,C,D,tol1=0.0,tol2=0.0,ldwork=None): Cr : rank-2 array, shape (p,nr) output matri of the controllable subsystem index : rank-1 array, shape (p) - array of orders of the denomenator polynomials + array of orders of the denominator polynomials dcoeff : rank-2 array, shape (p,max(index)+1) - array of denomenator coefficients + array of denominator coefficients ucoeff : rank-3 array, shape (p,m,max(index)+1) array of numerator coefficients @@ -576,9 +576,9 @@ def tb05ad(n, m, p, jomega, A, B, C, job='NG'): def td04ad(rowcol,m,p,index,dcoeff,ucoeff,tol=0.0,ldwork=None): - """ nr,A,B,C,D = td04ad(m,p,index,dcoeff,ucoeff,[tol,ldwork]) + """ nr,A,B,C,D = td04ad(rowcol,m,p,index,dcoeff,ucoeff,[tol,ldwork]) - Convert a tranfer function or matrix of transfer functions to + Convert a transfer function or matrix of transfer functions to a minimum state space realization. Required arguments @@ -592,11 +592,11 @@ def td04ad(rowcol,m,p,index,dcoeff,ucoeff,tol=0.0,ldwork=None): p : integer output dimension index : rank-1 array, shape (p) or (m) - array of orders of the denomenator polynomials. Different + array of orders of the denominator polynomials. Different shapes corresponding to rowcol=='R' and rowcol=='C' respectively. dcoeff : rank-2 array, shape (p,max(index)+1) or (m,max(index)+1) - array of denomenator coefficients. Different shapes + array of denominator coefficients. Different shapes corresponding to rowcol=='R' and rowcol=='C' respectively. ucoeff : rank-3 array, shape (p,m,max(index)+1) or (max(p,m),max(p,m),max(index)+1) array of numerator coefficients. Different shapes
