Skip to content

Commit d1b6b80

Browse files
author
Kevin Chen
committed
Added hsvd and markov functionality and test script TestModelsimp.py.
Steven Brunton <sbrunton@princeton.edu>
1 parent 72f2cf4 commit d1b6b80

3 files changed

Lines changed: 61 additions & 11 deletions

File tree

src/TestModelsimp.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env python
2+
3+
from modelsimp import *
4+
from matlab import *
5+
import numpy as np
6+
import unittest
7+
8+
class TestModelsimp(unittest.TestCase):
9+
def testHSVD(self):
10+
A = np.matrix("1. -2.; 3. -4.")
11+
B = np.matrix("5.; 7.")
12+
C = np.matrix("6. 8.")
13+
D = np.matrix("9.")
14+
sys = ss(A,B,C,D)
15+
hsv = hsvd(sys)
16+
hsvtrue = np.matrix("24.42686 0.5731395")
17+
np.testing.assert_array_almost_equal(hsv, hsvtrue)
18+
19+
def testMarkov(self):
20+
U = np.matrix("1.; 1.; 1.; 1.; 1.")
21+
Y = U
22+
M = 3
23+
H = markov(Y,U,M)
24+
Htrue = np.matrix("1.; 0.; 0.")
25+
np.testing.assert_array_almost_equal( H, Htrue )
26+
27+
if __name__ == '__main__':
28+
unittest.main()

src/TestStatefbk.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ def testGramWc(self):
4848
B = np.matrix("5. 6.; 7. 8.")
4949
C = np.matrix("4. 5.; 6. 7.")
5050
D = np.matrix("13. 14.; 15. 16.")
51-
# sys = ss(A, B, C, D)
52-
sys = 1.
51+
sys = ss(A, B, C, D)
5352
Wctrue = np.matrix("18.5 24.5; 24.5 32.5")
5453
Wc = gram(sys,'c')
5554
np.testing.assert_array_almost_equal(Wc, Wctrue)
@@ -60,7 +59,6 @@ def testGramWo(self):
6059
C = np.matrix("4. 5.; 6. 7.")
6160
D = np.matrix("13. 14.; 15. 16.")
6261
sys = ss(A, B, C, D)
63-
sys = 1.
6462
Wotrue = np.matrix("257.5 -94.5; -94.5 56.5")
6563
Wo = gram(sys,'o')
6664
np.testing.assert_array_almost_equal(Wo, Wotrue)

src/modelsimp.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ def hsvd(sys):
5353
=====
5454
H = hsvd(sys)
5555
56+
The Hankel singular values are the singular values of the Hankel operator. In practice, we compute the square root of the eigenvalues of the matrix formed by taking the product of the observability and controllability gramians. There are other (more efficient) methods based on solving the Lyapunov equation in a particular way (more details soon).
57+
5658
Inputs
5759
------
5860
sys : a state space system
@@ -63,15 +65,16 @@ def hsvd(sys):
6365
6466
"""
6567

66-
# Make sure that SLICOT is installed
67-
try:
68-
from slycot import sb01bd
69-
except ImportError:
70-
raise ControlSlycot("can't find slycot module 'sb01bd'")
71-
72-
H = 1.
68+
Wc = gram(sys,'c')
69+
Wo = gram(sys,'o')
70+
71+
WoWc = np.dot(Wo, Wc)
72+
w, v = LA.eig(WoWc)
73+
74+
hsv = np.sqrt(w)
75+
hsv = np.matrix(hsv)
7376
# Return the Hankel singular values
74-
return H
77+
return hsv
7578

7679
def era(YY,m,n,nin,nout,r):
7780
"""Calculate an ERA model of order r based on the impulse-response data YY
@@ -100,6 +103,7 @@ def markov(Y,U,M):
100103
Usage
101104
=====
102105
H = markov(Y,U,M)
106+
Currently only works for SISO
103107
104108
Inputs
105109
------
@@ -113,3 +117,23 @@ def markov(Y,U,M):
113117
114118
"""
115119

120+
# Convert input parameters to matrices (if they aren't already)
121+
Ymat = np.mat(Y)
122+
Umat = np.mat(U)
123+
n = np.size(U)
124+
125+
# Construct a matrix of control inputs to invert
126+
UU = Umat
127+
for i in range(1, M-1):
128+
newCol = np.vstack((0, UU[0:n-1,i-2]))
129+
UU = np.hstack((UU, newCol))
130+
Ulast = np.vstack((0, UU[0:n-1,M-2]))
131+
for i in range(n-1,0,-1):
132+
Ulast[i] = np.sum(Ulast[0:i-1])
133+
UU = np.hstack((UU, Ulast))
134+
135+
# Invert and solve for Markov parameters
136+
H = UU.I
137+
H = np.dot(H, Y)
138+
139+
return H

0 commit comments

Comments
 (0)