178 lines
7.1 KiB
Python
178 lines
7.1 KiB
Python
#!/usr/bin/env python
|
|
#
|
|
# modelsimp_test.py - test model reduction functions
|
|
# RMM, 30 Mar 2011 (based on TestModelSimp from v0.4a)
|
|
|
|
import unittest
|
|
import numpy as np
|
|
import warnings
|
|
import control
|
|
from control.modelsimp import *
|
|
from control.matlab import *
|
|
from control.exception import slycot_check
|
|
|
|
class TestModelsimp(unittest.TestCase):
|
|
def setUp(self):
|
|
# Use array instead of matrix (and save old value to restore at end)
|
|
control.use_numpy_matrix(False)
|
|
|
|
@unittest.skipIf(not slycot_check(), "slycot not installed")
|
|
def testHSVD(self):
|
|
A = np.array([[1., -2.], [3., -4.]])
|
|
B = np.array([[5.], [7.]])
|
|
C = np.array([[6., 8.]])
|
|
D = np.array([[9.]])
|
|
sys = ss(A,B,C,D)
|
|
hsv = hsvd(sys)
|
|
hsvtrue = np.array([24.42686, 0.5731395]) # from MATLAB
|
|
np.testing.assert_array_almost_equal(hsv, hsvtrue)
|
|
|
|
# Make sure default type values are correct
|
|
self.assertTrue(isinstance(hsv, np.ndarray))
|
|
self.assertFalse(isinstance(hsv, np.matrix))
|
|
|
|
# Check that using numpy.matrix does *not* affect answer
|
|
with warnings.catch_warnings(record=True) as w:
|
|
control.use_numpy_matrix(True)
|
|
self.assertTrue(issubclass(w[-1].category, UserWarning))
|
|
|
|
# Redefine the system (using np.matrix for storage)
|
|
sys = ss(A, B, C, D)
|
|
|
|
# Compute the Hankel singular value decomposition
|
|
hsv = hsvd(sys)
|
|
|
|
# Make sure that return type is correct
|
|
self.assertTrue(isinstance(hsv, np.ndarray))
|
|
self.assertFalse(isinstance(hsv, np.matrix))
|
|
|
|
# Go back to using the normal np.array representation
|
|
control.use_numpy_matrix(False)
|
|
|
|
def testMarkov(self):
|
|
U = np.array([[1.], [1.], [1.], [1.], [1.]])
|
|
Y = U
|
|
M = 3
|
|
H = markov(Y,U,M)
|
|
Htrue = np.array([[1.], [0.], [0.]])
|
|
np.testing.assert_array_almost_equal( H, Htrue )
|
|
|
|
def testModredMatchDC(self):
|
|
#balanced realization computed in matlab for the transfer function:
|
|
# num = [1 11 45 32], den = [1 15 60 200 60]
|
|
A = np.array(
|
|
[[-1.958, -1.194, 1.824, -1.464],
|
|
[-1.194, -0.8344, 2.563, -1.351],
|
|
[-1.824, -2.563, -1.124, 2.704],
|
|
[-1.464, -1.351, -2.704, -11.08]])
|
|
B = np.array([[-0.9057], [-0.4068], [-0.3263], [-0.3474]])
|
|
C = np.array([[-0.9057, -0.4068, 0.3263, -0.3474]])
|
|
D = np.array([[0.]])
|
|
sys = ss(A,B,C,D)
|
|
rsys = modred(sys,[2, 3],'matchdc')
|
|
Artrue = np.array([[-4.431, -4.552], [-4.552, -5.361]])
|
|
Brtrue = np.array([[-1.362], [-1.031]])
|
|
Crtrue = np.array([[-1.362, -1.031]])
|
|
Drtrue = np.array([[-0.08384]])
|
|
np.testing.assert_array_almost_equal(rsys.A, Artrue,decimal=3)
|
|
np.testing.assert_array_almost_equal(rsys.B, Brtrue,decimal=3)
|
|
np.testing.assert_array_almost_equal(rsys.C, Crtrue,decimal=3)
|
|
np.testing.assert_array_almost_equal(rsys.D, Drtrue,decimal=2)
|
|
|
|
def testModredUnstable(self):
|
|
# Check if an error is thrown when an unstable system is given
|
|
A = np.array(
|
|
[[4.5418, 3.3999, 5.0342, 4.3808],
|
|
[0.3890, 0.3599, 0.4195, 0.1760],
|
|
[-4.2117, -3.2395, -4.6760, -4.2180],
|
|
[0.0052, 0.0429, 0.0155, 0.2743]])
|
|
B = np.array([[1.0, 1.0], [2.0, 2.0], [3.0, 3.0], [4.0, 4.0]])
|
|
C = np.array([[1.0, 2.0, 3.0, 4.0], [1.0, 2.0, 3.0, 4.0]])
|
|
D = np.array([[0.0, 0.0], [0.0, 0.0]])
|
|
sys = ss(A,B,C,D)
|
|
np.testing.assert_raises(ValueError, modred, sys, [2, 3])
|
|
|
|
def testModredTruncate(self):
|
|
#balanced realization computed in matlab for the transfer function:
|
|
# num = [1 11 45 32], den = [1 15 60 200 60]
|
|
A = np.array(
|
|
[[-1.958, -1.194, 1.824, -1.464],
|
|
[-1.194, -0.8344, 2.563, -1.351],
|
|
[-1.824, -2.563, -1.124, 2.704],
|
|
[-1.464, -1.351, -2.704, -11.08]])
|
|
B = np.array([[-0.9057], [-0.4068], [-0.3263], [-0.3474]])
|
|
C = np.array([[-0.9057, -0.4068, 0.3263, -0.3474]])
|
|
D = np.array([[0.]])
|
|
sys = ss(A,B,C,D)
|
|
rsys = modred(sys,[2, 3],'truncate')
|
|
Artrue = np.array([[-1.958, -1.194], [-1.194, -0.8344]])
|
|
Brtrue = np.array([[-0.9057], [-0.4068]])
|
|
Crtrue = np.array([[-0.9057, -0.4068]])
|
|
Drtrue = np.array([[0.]])
|
|
np.testing.assert_array_almost_equal(rsys.A, Artrue)
|
|
np.testing.assert_array_almost_equal(rsys.B, Brtrue)
|
|
np.testing.assert_array_almost_equal(rsys.C, Crtrue)
|
|
np.testing.assert_array_almost_equal(rsys.D, Drtrue)
|
|
|
|
|
|
@unittest.skipIf(not slycot_check(), "slycot not installed")
|
|
def testBalredTruncate(self):
|
|
#controlable canonical realization computed in matlab for the transfer function:
|
|
# num = [1 11 45 32], den = [1 15 60 200 60]
|
|
A = np.array(
|
|
[[-15., -7.5, -6.25, -1.875],
|
|
[8., 0., 0., 0.],
|
|
[0., 4., 0., 0.],
|
|
[0., 0., 1., 0.]])
|
|
B = np.array([[2.], [0.], [0.], [0.]])
|
|
C = np.array([[0.5, 0.6875, 0.7031, 0.5]])
|
|
D = np.array([[0.]])
|
|
sys = ss(A,B,C,D)
|
|
orders = 2
|
|
rsys = balred(sys,orders,method='truncate')
|
|
Artrue = np.array([[-1.958, -1.194], [-1.194, -0.8344]])
|
|
Brtrue = np.array([[0.9057], [0.4068]])
|
|
Crtrue = np.array([[0.9057, 0.4068]])
|
|
Drtrue = np.array([[0.]])
|
|
np.testing.assert_array_almost_equal(rsys.A, Artrue,decimal=2)
|
|
np.testing.assert_array_almost_equal(rsys.B, Brtrue,decimal=4)
|
|
np.testing.assert_array_almost_equal(rsys.C, Crtrue,decimal=4)
|
|
np.testing.assert_array_almost_equal(rsys.D, Drtrue,decimal=4)
|
|
|
|
@unittest.skipIf(not slycot_check(), "slycot not installed")
|
|
def testBalredMatchDC(self):
|
|
#controlable canonical realization computed in matlab for the transfer function:
|
|
# num = [1 11 45 32], den = [1 15 60 200 60]
|
|
A = np.array(
|
|
[[-15., -7.5, -6.25, -1.875],
|
|
[8., 0., 0., 0.],
|
|
[0., 4., 0., 0.],
|
|
[0., 0., 1., 0.]])
|
|
B = np.array([[2.], [0.], [0.], [0.]])
|
|
C = np.array([[0.5, 0.6875, 0.7031, 0.5]])
|
|
D = np.array([[0.]])
|
|
sys = ss(A,B,C,D)
|
|
orders = 2
|
|
rsys = balred(sys,orders,method='matchdc')
|
|
Artrue = np.array(
|
|
[[-4.43094773, -4.55232904],
|
|
[-4.55232904, -5.36195206]])
|
|
Brtrue = np.array([[1.36235673], [1.03114388]])
|
|
Crtrue = np.array([[1.36235673, 1.03114388]])
|
|
Drtrue = np.array([[-0.08383902]])
|
|
np.testing.assert_array_almost_equal(rsys.A, Artrue,decimal=2)
|
|
np.testing.assert_array_almost_equal(rsys.B, Brtrue,decimal=4)
|
|
np.testing.assert_array_almost_equal(rsys.C, Crtrue,decimal=4)
|
|
np.testing.assert_array_almost_equal(rsys.D, Drtrue,decimal=4)
|
|
|
|
def tearDown(self):
|
|
# Reset configuration variables to their original settings
|
|
control.config.reset_defaults()
|
|
|
|
def suite():
|
|
return unittest.TestLoader().loadTestsFromTestCase(TestModelsimp)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|