Accepting request 746657 from devel:languages:python:numeric
- fix unittests to pass on all architectures * fix-test-sg03ad.patch see upstream PR#82 * fix-test-td04ad.patch see upstream PR#83 OBS-URL: https://build.opensuse.org/request/show/746657 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/python-slycot?expand=0&rev=5
This commit is contained in:
74
fix-test-sg03ad.patch
Normal file
74
fix-test-sg03ad.patch
Normal file
@@ -0,0 +1,74 @@
|
||||
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()
|
||||
312
fix-test-td04ad.patch
Normal file
312
fix-test-td04ad.patch
Normal file
@@ -0,0 +1,312 @@
|
||||
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
|
||||
@@ -1,3 +1,10 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Nov 8 13:30:41 UTC 2019 - Benjamin Greiner <code@bnavigator.de>
|
||||
|
||||
- fix unittests to pass on all architectures
|
||||
* fix-test-sg03ad.patch see upstream PR#82
|
||||
* fix-test-td04ad.patch see upstream PR#83
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Sun Sep 22 16:42:44 UTC 2019 - Benjamin Greiner <code@bnavigator.de>
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ License: GPL-2.0-only
|
||||
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 @@ Slycot is a wrapper for the SLICOT control and systems library.
|
||||
|
||||
%prep
|
||||
%setup -q -n slycot-%{version}
|
||||
%patch0 -p1
|
||||
%patch1 -p1
|
||||
|
||||
%build
|
||||
export CFLAGS="%{optflags}"
|
||||
|
||||
Reference in New Issue
Block a user