Skip to content

Commit 50fc081

Browse files
committed
added eig for symmetric matrix; fixed bug in dot
1 parent 3cc67fd commit 50fc081

File tree

7 files changed

+171
-62
lines changed

7 files changed

+171
-62
lines changed

pyobs/core/README

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
uwerr deprecated

pyobs/core/libcore.py

+18-4
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,37 @@
2222
##################################################
2323

2424

25+
def gamma_fft(Wmax,data1,data2=None):
26+
aux1=numpy.fft.fft(data1)
27+
if (data2 is not None):
28+
if (len(data2)!=len(data1)):
29+
raise
30+
else:
31+
aux2=numpy.fft.fft(data2)
32+
else:
33+
aux2=aux1
34+
35+
tmp = numpy.fft.ifft(aux1*numpy.conj(aux2))
36+
return tmp[0:Wmax+1].real
37+
38+
2539
def gamma(Wmax,data1,data2=None):
2640
N=len(data1)
27-
g = numpy.zeros(Wmax, dtype=numpy.double)
41+
g = numpy.zeros(Wmax+1, dtype=numpy.double)
2842

2943
if (data2 is not None):
3044
if (len(data2)!=N):
3145
raise
3246
else:
3347
data2 = data1
3448

35-
for t in range(Wmax):
49+
for t in range(Wmax+1):
3650
g[t] = data1[0:N-t].dot(data2[t:N])
3751

3852
return g
3953

4054
def normalize_gamma(gamma, Wmax, N, R):
41-
n = N-R*numpy.arange(0.,Wmax,1.)
55+
n = N-R*numpy.arange(0.,Wmax+1,1.)
4256
nn = 1.0/n
4357
return numpy.multiply(gamma, nn)
4458

@@ -78,7 +92,7 @@ def find_window(rho, N, Stau, texp=None):
7892
flag=0
7993
for W in range(1,Wmax):
8094
rho_int = rho_int + rho[W]
81-
tauW = Stau/numpy.log((rho_int+1.)/rho_int)
95+
tauW = Stau/numpy.log(numpy.fabs((rho_int+1.)/rho_int))
8296
gW = numpy.exp(-W/tauW) - tauW/numpy.sqrt(W*N)
8397
if (gW<0):
8498
Wopt = W

pyobs/core/utils.py

+23-22
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def fill_holes(idx_in, data_in, size=1):
3333
N = idx_in[-1] - idx_in[0] + 1
3434
idx = numpy.arange(idx_in[0],idx_in[-1]+1,1)
3535
data = numpy.array(numpy.zeros(N*size), dtype=numpy.double)
36-
36+
3737
norm = float(N)/float(len(data_in)/size)
3838
j=0
3939
for i in range(N):
@@ -48,36 +48,37 @@ def pad_with_zeros(data, before, after):
4848
S = numpy.shape(data)
4949
n0 = S[-1]
5050
data2 = numpy.zeros( S[0:-1]+(before+n0+after,) )
51+
norm = float(before+n0+after)/float(n0)
5152
for i in range(before, before+n0):
5253
data2[:,:,i] = numpy.array(data[:,:,i-before])
53-
return data2
54+
return data2 * norm
5455

5556
# returns the sorted union of the two lists
5657
def union(a,b):
57-
u = set(a) | set(b)
58-
return list(u)
58+
u = sorted(set(a) | set(b))
59+
return list(u)
5960

6061
def double_union(a,b,an,bn):
61-
u = list(set(a) | set(b))
62-
un = []
63-
for iu in u:
64-
try:
65-
un.append( an[a.index(iu)] )
66-
except:
67-
un.append( bn[b.index(iu)] )
68-
return [u, un]
62+
u = list(sorted(set(a) | set(b)))
63+
un = []
64+
for iu in u:
65+
try:
66+
un.append( an[a.index(iu)] )
67+
except:
68+
un.append( bn[b.index(iu)] )
69+
return [u, un]
6970

7071
def contains(a,b):
71-
for i in b:
72-
if (a==b):
73-
return b.index(a)
74-
return -1
72+
for i in b:
73+
if (a==b):
74+
return b.index(a)
75+
return -1
7576

7677

7778
def piechart(x,l,t):
78-
plt.subplots()
79-
plt.title('Components (%d,%d)' % t)
80-
x2 = numpy.array(x)/numpy.sum(x)
81-
plt.pie(x2,labels=l, autopct='%.0f%%',radius=1.0)
82-
plt.axis('equal')
83-
plt.show()
79+
plt.subplots()
80+
plt.title('Components (%d,%d)' % t)
81+
x2 = numpy.array(x)/numpy.sum(x)
82+
plt.pie(x2,labels=l, autopct='%.0f%%',radius=1.0)
83+
plt.axis('equal')
84+
plt.show()

pyobs/core/uwerr.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@
77

88
__all__ = ['uwerr']
99

10-
def uwerr(data,ncnfg,plot=False,opts=(),Stau=1.5,W=None):
10+
def uwerr(data,data2,ncnfg,plot=False,opts=(),Stau=1.5,W=None):
1111
R=len(ncnfg)
1212
N = numpy.sum(ncnfg)
1313
Wmax = min(ncnfg)/2
1414

1515
gg = numpy.zeros(Wmax, dtype=numpy.double)
1616
for ir in range(R):
17-
gg = gg + gamma(Wmax, data[ir])
17+
if data2 is None:
18+
gg = gg + gamma_fft(Wmax, data[ir])
19+
else:
20+
gg = gg + gamma_fft(Wmax, data[ir], data2[ir])
1821
gg2 = normalize_gamma(gg, Wmax, N, R)
1922

2023
if (W==None):
@@ -26,14 +29,12 @@ def uwerr(data,ncnfg,plot=False,opts=(),Stau=1.5,W=None):
2629
gg3 = correct_gamma_bias(gg2, Wopt, N)
2730
res = tauint(gg3,Wopt,N)
2831

29-
if (plot==True) or isinstance(plot,str):
32+
if (plot==True):
3033
rho = gg3/gg3[0]
3134
drho = libcore.compute_drho(rho,N)
3235

3336
if (plot==True):
34-
_rho_plotter(rho,drho,Wmax,Wopt,res[1:3],opts)
35-
if isinstance(plot,str):
36-
_rho_plotter(rho,drho,Wmax,Wopt,res[1:3],opts,plot)
37+
_rho_plotter(rho,drho,Wmax,Wopt,res[1:3],opts[:-1],opts[-1])
3738

3839
return res
3940

pyobs/ensdata.py

+67-25
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import numpy
22
import matplotlib.pyplot as plt
33

4-
from .vwerr import uwerr, uwerr_texp
4+
from .vwerr import uwerr, uwerr_texp, normac
55
from .core.utils import fill_holes, irregular_measurements
66
from .jerr import jackknife_error
77

@@ -67,11 +67,53 @@ def uwerr(self,plot,pfile,pars=(1.5,None)):
6767
dtau = numpy.zeros(self.dims)
6868
for i in range(self.dims[0]):
6969
for j in range(self.dims[1]):
70-
res = uwerr([rd.data[i,j] for rd in self.rdata], [rd.ncnfg for rd in self.rdata], plot, (self.name,i,j,pfile), pars[0], pars[1])
70+
res = uwerr([rd.data[i,j] for rd in self.rdata], None,
71+
[rd.ncnfg for rd in self.rdata],
72+
plot, (self.name,i,j,pfile), pars[0], pars[1])
7173
sigma[i,j] = res[0]
7274
tau[i,j] = res[1]
7375
dtau[i,j] = res[2]
7476
return [sigma, tau, dtau]
77+
78+
79+
def uwcov(self,plot,pars=(1.5,None)):
80+
if isinstance(plot,str):
81+
raise TypeError('uwcov: saving of plots to file not supported');
82+
sigma = numpy.zeros(self.dims+self.dims)
83+
tau = numpy.zeros(self.dims+self.dims)
84+
dtau = numpy.zeros(self.dims+self.dims)
85+
for i in range(self.dims[0]):
86+
for k in range(i,self.dims[0]):
87+
for j in range(self.dims[1]):
88+
for l in range(j,self.dims[1]):
89+
res = uwerr([rd.data[i,j] for rd in self.rdata],
90+
[rd.data[k,l] for rd in self.rdata],
91+
[rd.ncnfg for rd in self.rdata],
92+
plot, (self.name,i,j,None), pars[0], pars[1])
93+
sigma[i,j,k,l] = res[0]
94+
tau[i,j,k,l] = res[1]
95+
dtau[i,j,k,l] = res[2]
96+
if (i!=k) or (j!=l):
97+
sigma[k,l,i,j] = res[0]
98+
tau[k,l,i,j] = res[1]
99+
dtau[k,l,i,j] = res[2]
100+
return [sigma, tau, dtau]
101+
102+
103+
def normac(self,Wmax):
104+
rho = numpy.zeros(self.dims+self.dims+(Wmax+1,))
105+
drho= numpy.zeros(self.dims+self.dims+(Wmax+1,))
106+
for i in range(self.dims[0]):
107+
for k in range(i,self.dims[0]):
108+
for j in range(self.dims[1]):
109+
for l in range(j,self.dims[1]):
110+
res = normac([rd.data[i,j] for rd in self.rdata],
111+
[rd.data[k,l] for rd in self.rdata],
112+
[rd.ncnfg for rd in self.rdata], Wmax)
113+
rho[i,j,k,l,:] = res[0]
114+
drho[i,j,k,l,:] = res[1]
115+
return [rho,drho]
116+
75117

76118
def uwerr_texp(self,plot,pfile,pars=(1.5,0.0,2,0,None)):
77119
sigma = numpy.zeros(self.dims)
@@ -89,8 +131,9 @@ def naive_err(self):
89131
sigma = numpy.zeros(self.dims)
90132
for i in range(self.dims[0]):
91133
for j in range(self.dims[1]):
92-
res = uwerr([rd.data[i,j] for rd in self.rdata], [rd.ncnfg for rd in self.rdata],
93-
False, (self.name,i,j,''), 1.5, 0)
134+
res = uwerr([rd.data[i,j] for rd in self.rdata], None,
135+
[rd.ncnfg for rd in self.rdata],
136+
False, (self.name,i,j,None), 1.5, 0)
94137
sigma[i,j] = res[0]
95138
return sigma
96139

@@ -131,21 +174,7 @@ def mean(self,data):
131174
def create(self,idx,data,mean):
132175
subtraction = numpy.array([mean for _ in range(len(idx))]).flatten()
133176
delta = data - subtraction
134-
135-
# check if data is irregular and fix it
136-
if (irregular_measurements(idx)==True):
137-
tmp = fill_holes(idx, delta)
138-
else:
139-
tmp = [idx, delta]
140-
141-
self.ncnfg = len(idx)
142-
self.idx = list(tmp[0])
143-
self.data = numpy.zeros(self.dims+(self.ncnfg,))
144-
for k in range(self.ncnfg):
145-
for i in range(self.dims[0]):
146-
for j in range(self.dims[1]):
147-
self.data[i,j,k] = tmp[1][ (k*self.dims[1] + i)*self.dims[0] + j]
148-
#self.data = numpy.reshape(tmp[1], (self.ncnfg,)+self.dims[::-1]).T
177+
self.fill(idx,delta)
149178

150179
def clone(self,full):
151180
res = rdata(self.id,self.name,self.dims)
@@ -157,13 +186,26 @@ def clone(self,full):
157186
res.data = numpy.zeros(self.dims + (self.ncnfg,))
158187
return res
159188

160-
def fill(self,idx,data=None):
161-
self.ncnfg = len(idx)
162-
self.idx = list(idx)
163-
if (data==None):
164-
self.data = numpy.zeros(self.dims + (self.ncnfg,))
189+
def fill(self,idx,delta=None):
190+
if delta is None:
191+
# fixes idx if irregular
192+
tmp = [numpy.arange(idx[0],idx[-1]+1,1), delta]
165193
else:
166-
self.data = numpy.array(data)
194+
# check if data is irregular and fix it
195+
if (irregular_measurements(idx)==True):
196+
tmp = fill_holes(idx, delta,numpy.prod(self.dims))
197+
else:
198+
tmp = [idx, delta]
199+
200+
self.ncnfg = len(tmp[0])
201+
self.idx = list(tmp[0])
202+
self.data = numpy.zeros(self.dims+(self.ncnfg,))
203+
if delta is None:
204+
return
205+
for k in range(self.ncnfg):
206+
for i in range(self.dims[0]):
207+
for j in range(self.dims[1]):
208+
self.data[i,j,k] = tmp[1][ (k*self.dims[0] + i)*self.dims[1] + j]
167209

168210

169211
class cdata:

pyobs/mathfcts.py

+27-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from sympy import Matrix, diff, lambdify
77

88
__all__ = ['math_sum','math_det','math_tr',
9-
'math_inv','math_add','math_mul',
9+
'math_inv','math_eig','math_add','math_mul',
1010
'math_dot','math_scalar','math_binary']
1111

1212

@@ -102,6 +102,28 @@ def math_inv(mean):
102102

103103
return [func, [grad]]
104104

105+
def math_eig(mean):
106+
dims = numpy.shape(mean)
107+
[w,v] = numpy.linalg.eig(mean)
108+
109+
gradw = numpy.zeros((dims[0],1)+dims)
110+
gradv = numpy.zeros(dims+dims)
111+
dfunc = numpy.zeros(dims)
112+
113+
for k in range(dims[0]):
114+
for l in range(dims[1]):
115+
dfunc[k,l] = 1.0
116+
tmp0 = (v.T).dot(dfunc).dot(v)
117+
dfunc[k,l] = 0.0
118+
for i in range(dims[0]):
119+
gradw[i,0,k,l] = tmp0[i,i]
120+
for j in range(dims[1]):
121+
if i!=j:
122+
gradv[:,i,k,l] += (tmp0[i,j]/(w[i]-w[j]))*v[:,j]
123+
func = [numpy.reshape(w,(dims[0],1)), v]
124+
dfunc = [gradw, gradv]
125+
return [func, dfunc]
126+
105127
#######################################################################
106128

107129
def math_add(mean1,mean2):
@@ -138,11 +160,13 @@ def math_dot(mean1,mean2):
138160
M2 = SymMat(d2,'M2')
139161

140162
s = Subs([mean1,mean2],[M1, M2])
141-
h = [[0]*d2[1]]*d1[0]
163+
h = []
142164
for i in range(d1[0]):
165+
hh = [0]*d2[1]
143166
for j in range(d2[1]):
144167
for k in range(d1[1]):
145-
h[i][j] = h[i][j] + M1[i,k]*M2[k,j]
168+
hh[j] = hh[j] + M1[i,k]*M2[k,j]
169+
h.append(hh)
146170
expr = Matrix(h)
147171
#expr = Matrix(M2.dot(M1)).reshape(d1[0],d2[1]).transpose()
148172

pyobs/observa.py

+28-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
__all__ = ['observa', 'derobs',
1616
'log', 'exp', 'sin', 'cos', 'arcsin', 'arccos',
1717
'sinh', 'cosh', 'arcsinh', 'arccosh',
18-
'trace', 'det', 'inv']
18+
'trace', 'det', 'inv','eig']
1919

2020
class InputError(Exception):
2121
pass
@@ -1034,6 +1034,32 @@ def inv(x):
10341034
return derobs([x], f, df)
10351035

10361036

1037+
def eig(x):
1038+
"""
1039+
Compute the eigenvalues and eigenvectors of a square symmetric matrix
1040+
1041+
Parameters
1042+
----------
1043+
x : observa
1044+
must be a square matrix
1045+
1046+
Returns
1047+
-------
1048+
w, v : observa
1049+
the eigenvalues and a matrix whose columns
1050+
correspond to the eigenvectors
1051+
1052+
Examples
1053+
--------
1054+
>>> [w, v] = eig(x)
1055+
"""
1056+
1057+
if (x.dims[0]!=x.dims[1]):
1058+
raise InputError('unsupported operation for non-square matrices')
1059+
[f, df] = math_eig(x.mean)
1060+
return [derobs([x], f[0], [df[0]]), derobs([x], f[1], [df[1]])]
1061+
1062+
10371063
def derobs(inps,func,dfunc=None):
10381064
""" Compute the derived observable from a given function.
10391065
It is highly recommended to avoid the usage of this function
@@ -1100,7 +1126,7 @@ def derobs(inps,func,dfunc=None):
11001126
grad = []
11011127
for i in range(len(inps)):
11021128
if dfunc is None:
1103-
grad.append( numerical_derivative(all_mean,func,i,inps[i].naive_err()) )
1129+
grad.append( numerical_derivative(all_mean,func,i,inps[i].naive_err()*1e-4) )
11041130
else:
11051131
grad.append( numpy.array(dfunc[i]) )
11061132

0 commit comments

Comments
 (0)