/
20110822a.py
188 lines (168 loc) · 5.29 KB
/
20110822a.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
"""
Look at Schur complements of specially structured matrices.
There is not really anything interesting here.
"""
from StringIO import StringIO
import numpy as np
import scipy
import scipy.linalg
import Form
import FormOut
import MatrixUtil
from MatrixUtil import double_centered_slow
from MatrixUtil import ndot
class Counterexample(Exception): pass
def get_form():
"""
@return: the body of a form
"""
# define the form objects
form_objects = []
return form_objects
def get_form_out():
return FormOut.Report()
def bott_duffin(M):
"""
We pretend that P_L is H.
"""
nrows, ncols = M.shape
if nrows != ncols:
raise ValueError('expected a square matrix')
e = np.ones(nrows)
I = np.eye(nrows)
P = np.outer(e, e) / np.inner(e, e)
H = I - P
return ndot(H, np.linalg.inv(np.dot(M, H) + P))
def pinvproj(M):
"""
This could be made more efficient using double centering.
"""
nrows, ncols = M.shape
if nrows != ncols:
raise ValueError('expected a square matrix')
e = np.ones(nrows)
I = np.eye(nrows)
P = np.outer(e, e) / np.inner(e, e)
H = I - P
HMH = ndot(H, M, H)
return np.linalg.inv(HMH + P) - P
def schur(M, nsmall):
B = M[:nsmall, nsmall:]
C = np.linalg.inv(M[nsmall:, nsmall:])
return M[:nsmall, :nsmall] - ndot(B, C, B.T)
def assert_named_equation(a_name_pair, b_name_pair):
"""
This is a helper function to check for counterexamples.
"""
a, a_name = a_name_pair
b, b_name = b_name_pair
if not np.allclose(a, b):
out = StringIO()
print >> out, a_name + ':'
print >> out, a
print >> out, b_name + ':'
print >> out, b
raise Counterexample(out.getvalue())
def assert_pinvproj(fs, M):
"""
Raise a Counterexample if one is found.
"""
pinvproj_of_sub = pinvproj(M[:fs.nsmall, :fs.nsmall])
schur_of_pinvproj = schur(pinvproj(M), fs.nsmall)
bottduff_of_sub = bott_duffin(M[:fs.nsmall, :fs.nsmall])
schur_of_bottduff = schur(bott_duffin(M), fs.nsmall)
assert_named_equation(
(pinvproj_of_sub, 'pinvproj of sub'),
(schur_of_pinvproj, 'schur of pinvproj'))
assert_named_equation(
(pinvproj_of_sub, 'pinvproj of sub'),
(bottduff_of_sub, 'bottduff of sub'))
assert_named_equation(
(schur_of_pinvproj, 'schur of pinvproj'),
(schur_of_bottduff, 'schur of bottduff'))
def inverse_in_H(M):
nrows, ncols = M.shape
if nrows != ncols:
raise ValueError('expected a square matrix')
e = np.ones(nrows)
I = np.eye(nrows)
P = np.outer(e, e) / np.inner(e, e)
return np.linalg.inv(M + P) - P
def assert_double_centering_identities(fs, M):
"""
Raise a Counterexample if one is found.
"""
A = M[:fs.nsmall, :fs.nsmall]
HMH = double_centered_slow(M)
HMH_A = HMH[:fs.nsmall, :fs.nsmall]
# check an identity between two ways to compute a centered submatrix
HAH_direct = double_centered_slow(A)
HAH_indirect = double_centered_slow(HMH_A)
assert_named_equation(
(HAH_direct, 'double centered submatrix'),
(HAH_indirect, 're-centered submatrix of doubly centered matrix'))
HAH = HAH_indirect
# This is not true:
# check that HAH <==inverse_in_H==> H A^-1 H
HAH_pinv = inverse_in_H(HAH)
H_Ainv_H = double_centered_slow(np.linalg.inv(A))
assert_named_equation(
(HAH_pinv, 'inverse-in-H of HAH'),
(H_Ainv_H, 'double centered inverse of A'))
# check a submatrix-schur-inverse commutativity in double centering
HMH_pinv = inverse_in_H(HMH)
schur_of_HMH_pinv = schur(HMH_pinv, fs.nsmall)
assert_named_equation(
(HAH_pinv, 'inverse-in-H of HAH'),
(schur_of_HMH_pinv, 'schur of pinv of HMH'))
def sample_edm(nbig):
"""
There is probably a nicer way to make an EDM.
"""
nrows = nbig
ncols = nbig-1
X = np.random.rand(nrows, ncols)
M = np.zeros((nbig, nbig))
for i in range(nbig):
for j in range(nbig):
d = X[i] - X[j]
M[i, j] = np.dot(d, d)
return M
def sample_sym(n):
M = 10 * (np.random.rand(n, n) - 0.5)
return M + M.T
def get_response_content(fs):
nbig = 10
nsmall = 4
e = np.ones(nbig)
I = np.eye(nbig)
Q = np.outer(e, e) / np.inner(e, e)
H = I - Q
M = sample_sym(nbig)
W = double_centered_slow(M)
WpQ = W + Q
# get eigendecomposition of schur complement
W_SC = schur(W, nsmall)
W_SC_w, W_SC_vt = scipy.linalg.eigh(W_SC)
# get eigendecomposition of schur complement
WpQ_SC = schur(WpQ, nsmall)
WpQ_SC_w, WpQ_SC_vt = scipy.linalg.eigh(WpQ_SC)
# show the results
out = StringIO()
np.set_printoptions(linewidth=200)
print >> out, 'random symmetric matrix:'
print >> out, M
print >> out, 'after centering:'
print >> out, W
print >> out, 'after adding a constant eigenvector with unit eigenvalue:'
print >> out, WpQ
print >> out
print >> out, 'eigendecomposition of Schur complement of centered matrix:'
print >> out, W_SC_w
print >> out, W_SC_vt
print >> out
print >> out, 'eigendecomposition of Schur complement of decentered matrix:'
print >> out, WpQ_SC_w
print >> out, WpQ_SC_vt
print >> out
return out.getvalue()