Merge pull request #107 from fjosw/fix/none_array_entries

Fix/none array entries
This commit is contained in:
Fabian Joswig 2022-06-13 13:31:18 +01:00 committed by GitHub
commit 090d2b1e1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 22 deletions

View file

@ -155,7 +155,7 @@ class Corr:
raise Exception("Vectors are of wrong shape!") raise Exception("Vectors are of wrong shape!")
if normalize: if normalize:
vector_l, vector_r = vector_l / np.sqrt((vector_l @ vector_l)), vector_r / np.sqrt(vector_r @ vector_r) vector_l, vector_r = vector_l / np.sqrt((vector_l @ vector_l)), vector_r / np.sqrt(vector_r @ vector_r)
newcontent = [None if (item is None) else np.asarray([vector_l.T @ item @ vector_r]) for item in self.content] newcontent = [None if _check_for_none(self, item) else np.asarray([vector_l.T @ item @ vector_r]) for item in self.content]
else: else:
# There are no checks here yet. There are so many possible scenarios, where this can go wrong. # There are no checks here yet. There are so many possible scenarios, where this can go wrong.
@ -163,7 +163,7 @@ class Corr:
for t in range(self.T): for t in range(self.T):
vector_l[t], vector_r[t] = vector_l[t] / np.sqrt((vector_l[t] @ vector_l[t])), vector_r[t] / np.sqrt(vector_r[t] @ vector_r[t]) vector_l[t], vector_r[t] = vector_l[t] / np.sqrt((vector_l[t] @ vector_l[t])), vector_r[t] / np.sqrt(vector_r[t] @ vector_r[t])
newcontent = [None if (self.content[t] is None or vector_l[t] is None or vector_r[t] is None) else np.asarray([vector_l[t].T @ self.content[t] @ vector_r[t]]) for t in range(self.T)] newcontent = [None if (_check_for_none(self, self.content[t]) or vector_l[t] is None or vector_r[t] is None) else np.asarray([vector_l[t].T @ self.content[t] @ vector_r[t]]) for t in range(self.T)]
return Corr(newcontent) return Corr(newcontent)
def item(self, i, j): def item(self, i, j):
@ -197,6 +197,8 @@ class Corr:
def symmetric(self): def symmetric(self):
""" Symmetrize the correlator around x0=0.""" """ Symmetrize the correlator around x0=0."""
if self.N != 1:
raise Exception('symmetric cannot be safely applied to multi-dimensional correlators.')
if self.T % 2 != 0: if self.T % 2 != 0:
raise Exception("Can not symmetrize odd T") raise Exception("Can not symmetrize odd T")
@ -215,6 +217,8 @@ class Corr:
def anti_symmetric(self): def anti_symmetric(self):
"""Anti-symmetrize the correlator around x0=0.""" """Anti-symmetrize the correlator around x0=0."""
if self.N != 1:
raise Exception('anti_symmetric cannot be safely applied to multi-dimensional correlators.')
if self.T % 2 != 0: if self.T % 2 != 0:
raise Exception("Can not symmetrize odd T") raise Exception("Can not symmetrize odd T")
@ -236,7 +240,7 @@ class Corr:
def matrix_symmetric(self): def matrix_symmetric(self):
"""Symmetrizes the correlator matrices on every timeslice.""" """Symmetrizes the correlator matrices on every timeslice."""
if self.N > 1: if self.N > 1:
transposed = [None if len(list(filter(None, np.asarray(G).flatten()))) < self.N ** 2 else G.T for G in self.content] transposed = [None if _check_for_none(self, G) else G.T for G in self.content]
return 0.5 * (Corr(transposed) + self) return 0.5 * (Corr(transposed) + self)
if self.N == 1: if self.N == 1:
raise Exception("Trying to symmetrize a correlator matrix, that already has N=1.") raise Exception("Trying to symmetrize a correlator matrix, that already has N=1.")
@ -419,13 +423,15 @@ class Corr:
Can either be an Obs which is correlated with all entries of the Can either be an Obs which is correlated with all entries of the
correlator or a Corr of same length. correlator or a Corr of same length.
""" """
if self.N != 1:
raise Exception("Only one-dimensional correlators can be safely correlated.")
new_content = [] new_content = []
for x0, t_slice in enumerate(self.content): for x0, t_slice in enumerate(self.content):
if t_slice is None: if _check_for_none(self, t_slice):
new_content.append(None) new_content.append(None)
else: else:
if isinstance(partner, Corr): if isinstance(partner, Corr):
if partner.content[x0] is None: if _check_for_none(partner, partner.content[x0]):
new_content.append(None) new_content.append(None)
else: else:
new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice])) new_content.append(np.array([correlate(o, partner.content[x0][0]) for o in t_slice]))
@ -449,9 +455,11 @@ class Corr:
the reweighting factor on all configurations in weight.idl and not the reweighting factor on all configurations in weight.idl and not
on the configurations in obs[i].idl. on the configurations in obs[i].idl.
""" """
if self.N != 1:
raise Exception("Reweighting only implemented for one-dimensional correlators.")
new_content = [] new_content = []
for t_slice in self.content: for t_slice in self.content:
if t_slice is None: if _check_for_none(self, t_slice):
new_content.append(None) new_content.append(None)
else: else:
new_content.append(np.array(reweight(weight, t_slice, **kwargs))) new_content.append(np.array(reweight(weight, t_slice, **kwargs)))
@ -467,6 +475,8 @@ class Corr:
partity : int partity : int
Parity quantum number of the correlator, can be +1 or -1 Parity quantum number of the correlator, can be +1 or -1
""" """
if self.N != 1:
raise Exception("T_symmetry only implemented for one-dimensional correlators.")
if not isinstance(partner, Corr): if not isinstance(partner, Corr):
raise Exception("T partner has to be a Corr object.") raise Exception("T partner has to be a Corr object.")
if parity not in [+1, -1]: if parity not in [+1, -1]:
@ -494,6 +504,8 @@ class Corr:
decides which definition of the finite differences derivative is used. decides which definition of the finite differences derivative is used.
Available choice: symmetric, forward, backward, improved, default: symmetric Available choice: symmetric, forward, backward, improved, default: symmetric
""" """
if self.N != 1:
raise Exception("deriv only implemented for one-dimensional correlators.")
if variant == "symmetric": if variant == "symmetric":
newcontent = [] newcontent = []
for t in range(1, self.T - 1): for t in range(1, self.T - 1):
@ -546,6 +558,8 @@ class Corr:
decides which definition of the finite differences derivative is used. decides which definition of the finite differences derivative is used.
Available choice: symmetric, improved, default: symmetric Available choice: symmetric, improved, default: symmetric
""" """
if self.N != 1:
raise Exception("second_deriv only implemented for one-dimensional correlators.")
if variant == "symmetric": if variant == "symmetric":
newcontent = [] newcontent = []
for t in range(1, self.T - 1): for t in range(1, self.T - 1):
@ -923,7 +937,7 @@ class Corr:
raise Exception("Addition of Corrs with different shape") raise Exception("Addition of Corrs with different shape")
newcontent = [] newcontent = []
for t in range(self.T): for t in range(self.T):
if (self.content[t] is None) or (y.content[t] is None): if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
newcontent.append(None) newcontent.append(None)
else: else:
newcontent.append(self.content[t] + y.content[t]) newcontent.append(self.content[t] + y.content[t])
@ -932,7 +946,7 @@ class Corr:
elif isinstance(y, (Obs, int, float, CObs)): elif isinstance(y, (Obs, int, float, CObs)):
newcontent = [] newcontent = []
for t in range(self.T): for t in range(self.T):
if (self.content[t] is None): if _check_for_none(self, self.content[t]):
newcontent.append(None) newcontent.append(None)
else: else:
newcontent.append(self.content[t] + y) newcontent.append(self.content[t] + y)
@ -951,7 +965,7 @@ class Corr:
raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T") raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
newcontent = [] newcontent = []
for t in range(self.T): for t in range(self.T):
if (self.content[t] is None) or (y.content[t] is None): if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
newcontent.append(None) newcontent.append(None)
else: else:
newcontent.append(self.content[t] * y.content[t]) newcontent.append(self.content[t] * y.content[t])
@ -960,7 +974,7 @@ class Corr:
elif isinstance(y, (Obs, int, float, CObs)): elif isinstance(y, (Obs, int, float, CObs)):
newcontent = [] newcontent = []
for t in range(self.T): for t in range(self.T):
if (self.content[t] is None): if _check_for_none(self, self.content[t]):
newcontent.append(None) newcontent.append(None)
else: else:
newcontent.append(self.content[t] * y) newcontent.append(self.content[t] * y)
@ -979,12 +993,12 @@ class Corr:
raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T") raise Exception("Multiplication of Corr object requires N=N or N=1 and T=T")
newcontent = [] newcontent = []
for t in range(self.T): for t in range(self.T):
if (self.content[t] is None) or (y.content[t] is None): if _check_for_none(self, self.content[t]) or _check_for_none(y, y.content[t]):
newcontent.append(None) newcontent.append(None)
else: else:
newcontent.append(self.content[t] / y.content[t]) newcontent.append(self.content[t] / y.content[t])
for t in range(self.T): for t in range(self.T):
if newcontent[t] is None: if _check_for_none(self, newcontent[t]):
continue continue
if np.isnan(np.sum(newcontent[t]).value): if np.isnan(np.sum(newcontent[t]).value):
newcontent[t] = None newcontent[t] = None
@ -1003,7 +1017,7 @@ class Corr:
newcontent = [] newcontent = []
for t in range(self.T): for t in range(self.T):
if (self.content[t] is None): if _check_for_none(self, self.content[t]):
newcontent.append(None) newcontent.append(None)
else: else:
newcontent.append(self.content[t] / y) newcontent.append(self.content[t] / y)
@ -1014,7 +1028,7 @@ class Corr:
raise Exception('Division by zero will return undefined correlator') raise Exception('Division by zero will return undefined correlator')
newcontent = [] newcontent = []
for t in range(self.T): for t in range(self.T):
if (self.content[t] is None): if _check_for_none(self, self.content[t]):
newcontent.append(None) newcontent.append(None)
else: else:
newcontent.append(self.content[t] / y) newcontent.append(self.content[t] / y)
@ -1028,7 +1042,7 @@ class Corr:
raise TypeError('Corr / wrong type') raise TypeError('Corr / wrong type')
def __neg__(self): def __neg__(self):
newcontent = [None if (item is None) else -1. * item for item in self.content] newcontent = [None if _check_for_none(self, item) else -1. * item for item in self.content]
return Corr(newcontent, prange=self.prange) return Corr(newcontent, prange=self.prange)
def __sub__(self, y): def __sub__(self, y):
@ -1036,31 +1050,31 @@ class Corr:
def __pow__(self, y): def __pow__(self, y):
if isinstance(y, (Obs, int, float, CObs)): if isinstance(y, (Obs, int, float, CObs)):
newcontent = [None if (item is None) else item**y for item in self.content] newcontent = [None if _check_for_none(self, item) else item**y for item in self.content]
return Corr(newcontent, prange=self.prange) return Corr(newcontent, prange=self.prange)
else: else:
raise TypeError('Type of exponent not supported') raise TypeError('Type of exponent not supported')
def __abs__(self): def __abs__(self):
newcontent = [None if (item is None) else np.abs(item) for item in self.content] newcontent = [None if _check_for_none(self, item) else np.abs(item) for item in self.content]
return Corr(newcontent, prange=self.prange) return Corr(newcontent, prange=self.prange)
# The numpy functions: # The numpy functions:
def sqrt(self): def sqrt(self):
return self**0.5 return self ** 0.5
def log(self): def log(self):
newcontent = [None if (item is None) else np.log(item) for item in self.content] newcontent = [None if _check_for_none(self, item) else np.log(item) for item in self.content]
return Corr(newcontent, prange=self.prange) return Corr(newcontent, prange=self.prange)
def exp(self): def exp(self):
newcontent = [None if (item is None) else np.exp(item) for item in self.content] newcontent = [None if _check_for_none(self, item) else np.exp(item) for item in self.content]
return Corr(newcontent, prange=self.prange) return Corr(newcontent, prange=self.prange)
def _apply_func_to_corr(self, func): def _apply_func_to_corr(self, func):
newcontent = [None if (item is None) else func(item) for item in self.content] newcontent = [None if _check_for_none(self, item) else func(item) for item in self.content]
for t in range(self.T): for t in range(self.T):
if newcontent[t] is None: if _check_for_none(self, newcontent[t]):
continue continue
if np.isnan(np.sum(newcontent[t]).value): if np.isnan(np.sum(newcontent[t]).value):
newcontent[t] = None newcontent[t] = None
@ -1222,6 +1236,11 @@ def _sort_vectors(vec_set, ts):
return sorted_vec_set return sorted_vec_set
def _check_for_none(corr, entry):
"""Checks if entry for correlator corr is None"""
return len(list(filter(None, np.asarray(entry).flatten()))) < corr.N ** 2
def _GEVP_solver(Gt, G0): def _GEVP_solver(Gt, G0):
"""Helper function for solving the GEVP and sorting the eigenvectors. """Helper function for solving the GEVP and sorting the eigenvectors.

View file

@ -246,6 +246,21 @@ def test_matrix_corr():
corr_mat.Eigenvalue(2, state=0) corr_mat.Eigenvalue(2, state=0)
def test_corr_none_entries():
a = pe.pseudo_Obs(1.0, 0.1, 'a')
l = np.asarray([[a, a], [a, a]])
n = np.asarray([[None, None], [None, None]])
x = [l, n]
matr = pe.Corr(x)
matr.projected(np.asarray([1.0, 0.0]))
matr * 2 - 2 * matr
matr * matr + matr ** 2 / matr
for func in [np.sqrt, np.log, np.exp, np.sin, np.cos, np.tan, np.sinh, np.cosh, np.tanh]:
func(matr)
def test_GEVP_warnings(): def test_GEVP_warnings():
corr_aa = _gen_corr(1) corr_aa = _gen_corr(1)
corr_ab = 0.5 * corr_aa corr_ab = 0.5 * corr_aa