diff --git a/docs/pyerrors/correlators.html b/docs/pyerrors/correlators.html index 502bbbc0..a3f979d6 100644 --- a/docs/pyerrors/correlators.html +++ b/docs/pyerrors/correlators.html @@ -86,6 +86,9 @@
def projected(self, vector_l=None, vector_r=None): +@@ -2167,24 +2475,47 @@ timeslice and the error on each timeslice. def - GEVP(self, t0, ts, state=1): + GEVP(self, t0, ts, state=0, sorting='Eigenvalue', return_list=False):def projected(self, vector_l=None, vector_r=None, normalize=False): if self.N == 1: raise Exception("Trying to project a Corr, that already has N=1.") # This Exception is in no way necessary. One could just return self @@ -1972,17 +2265,32 @@ region indentified for this correlator. vector_l, vector_r = np.asarray([1.] + (self.N - 1) * [0.]), np.asarray([1.] + (self.N - 1) * [0.]) elif(vector_r is None): vector_r = vector_l + if isinstance(vector_l, list) and not isinstance(vector_r, list): + if len(vector_l) != self.T: + raise Exception("Length of vector list must be equal to T") + vector_r = [vector_r] * self.T + if isinstance(vector_r, list) and not isinstance(vector_l, list): + if len(vector_r) != self.T: + raise Exception("Length of vector list must be equal to T") + vector_l = [vector_l] * self.T - if not vector_l.shape == vector_r.shape == (self.N,): - raise Exception("Vectors are of wrong shape!") + if not isinstance(vector_l, list): + if not vector_l.shape == vector_r.shape == (self.N,): + raise Exception("Vectors are of wrong shape!") + if normalize: + vector_l, vector_r = vector_l / np.sqrt((vector_l @ vector_l)), vector_r / np.sqrt(vector_r @ vector_r) + # if (not (0.95 < vector_r @ vector_r < 1.05)) or (not (0.95 < vector_l @ vector_l < 1.05)): + # print("Vectors are normalized before projection!") - # We always normalize before projecting! But we only raise a warning, when it is clear, they where not meant to be normalized. - if (not (0.95 < vector_r @ vector_r < 1.05)) or (not (0.95 < vector_l @ vector_l < 1.05)): - print("Vectors are normalized before projection!") + newcontent = [None if (item is None) else np.asarray([vector_l.T @ item @ vector_r]) for item in self.content] - vector_l, vector_r = vector_l / np.sqrt((vector_l @ vector_l)), vector_r / np.sqrt(vector_r @ vector_r) + else: + # There are no checks here yet. There are so many possible scenarios, where this can go wrong. + if normalize: + 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]) - newcontent = [None if (item is None) else np.asarray([vector_l.T @ item @ vector_r]) for item in self.content] + 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)] return Corr(newcontent)
def GEVP(self, t0, ts, state=1): - if (self.content[t0] is None) or (self.content[ts] is None): - raise Exception("Corr not defined at t0/ts") - G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double") - for i in range(self.N): - for j in range(self.N): - G0[i, j] = self.content[t0][i, j].value - Gt[i, j] = self.content[ts][i, j].value +@@ -2211,11 +2542,14 @@ timeslice and the error on each timeslice. LTi = inv(LT) newcontent = [] for t in range(self.T): - Gt = G.content[t] - M = Li @ Gt @ LTi - eigenvalues = eigh(M)[0] - eigenvalue = eigenvalues[-state] - newcontent.append(eigenvalue) + if self.content[t] is None: + newcontent.append(None) + else: + Gt = G.content[t] + M = Li @ Gt @ LTi + eigenvalues = eigh(M)[0] + eigenvalue = eigenvalues[-state] + newcontent.append(eigenvalue) return Corr(newcontent)def GEVP(self, t0, ts, state=0, sorting="Eigenvalue", return_list=False): + if not return_list: + if (self.content[t0] is None) or (self.content[ts] is None): + raise Exception("Corr not defined at t0/ts") + G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double") + for i in range(self.N): + for j in range(self.N): + G0[i, j] = self.content[t0][i, j].value + Gt[i, j] = self.content[ts][i, j].value - sp_val, sp_vec = scipy.linalg.eig(Gt, G0) - sp_vec = sp_vec[:, np.argsort(sp_val)[-state]] # We only want the eigenvector belonging to the selected state - sp_vec = sp_vec / np.sqrt(sp_vec @ sp_vec) - return sp_vec + sp_vecs = GEVP_solver(Gt, G0) + sp_vec = sp_vecs[state] + return sp_vec + if return_list: + all_vecs = [] + for t in range(self.T): + try: + G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double") + for i in range(self.N): + for j in range(self.N): + G0[i, j] = self.content[t0][i, j].value + Gt[i, j] = self.content[t][i, j].value + + sp_vecs = GEVP_solver(Gt, G0) + if sorting == "Eigenvalue": + sp_vec = sp_vecs[state] + all_vecs.append(sp_vec) + else: + all_vecs.append(sp_vecs) + except "Failure to solve for one timeslice": # This could contain a check for real eigenvectors + all_vecs.append(None) + if sorting == "Eigenvector": + all_vecs = sort_vectors(all_vecs, ts) + all_vecs = [a[state] for a in all_vecs] + + return all_vecs
def Hankel(self, N, periodic=False): + # Constructs an NxN Hankel matrix + # C(t) c(t+1) ... c(t+n-1) + # C(t+1) c(t+2) ... c(t+n) + # ................. + # C(t+(n-1)) c(t+n) ... c(t+2(n-1)) + + if self.N != 1: + raise Exception("Multi-operator Prony not implemented!") + + array = np.empty([N, N], dtype="object") + new_content = [] + for t in range(self.T): + new_content.append(array.copy()) + + def wrap(i): + if i >= self.T: + return i - self.T + return i + + for t in range(self.T): + for i in range(N): + for j in range(N): + if periodic: + new_content[t][i, j] = self.content[wrap(t + i + j)][0] + elif (t + i + j) >= self.T: + new_content[t] = None + else: + new_content[t][i, j] = self.content[t + i + j][0] + + return Corr(new_content) +
def reverse(self): """Reverse the time ordering of the Corr""" - return Corr(self.content[::-1]) + return Corr(self.content[:: -1])
def dump(self, filename, **kwargs): """Dumps the Corr into a pickle file - Parameters ---------- filename : str @@ -2929,6 +3310,7 @@ path to file in which the figure should be saved specifies a custom path for the file (default '.') """ dump_object(self, filename, **kwargs) + return
def sort_vectors(vec_set, ts): # Helper function used to find a set of Eigenvectors consistent over all timeslices + reference_sorting = np.array(vec_set[ts]) + N = reference_sorting.shape[0] + sorted_vec_set = [] + for t in range(len(vec_set)): + if vec_set[t] is None: + sorted_vec_set.append(None) + elif not t == ts: + perms = permutation([i for i in range(N)]) + best_score = 0 + for perm in perms: + current_score = 1 + for k in range(N): + new_sorting = reference_sorting.copy() + new_sorting[perm[k], :] = vec_set[t][k] + current_score *= abs(np.linalg.det(new_sorting)) + if current_score > best_score: + best_score = current_score + best_perm = perm + # print("best perm", best_perm) + sorted_vec_set.append([vec_set[t][k] for k in best_perm]) + else: + sorted_vec_set.append(vec_set[t]) + + return sorted_vec_set +
def permutation(lst): # Shamelessly copied + if len(lst) == 1: + return [lst] + ll = [] + for i in range(len(lst)): + m = lst[i] + remLst = lst[:i] + lst[i + 1:] + # Generating all permutations where m is first + for p in permutation(remLst): + ll.append([m] + p) + return ll +
def GEVP_solver(Gt, G0): # Just so normalization an sorting does not need to be repeated. Here we could later put in some checks + sp_val, sp_vecs = scipy.linalg.eig(Gt, G0) + sp_vecs = [sp_vecs[:, np.argsort(sp_val)[-i]] for i in range(1, sp_vecs.shape[0] + 1)] + sp_vecs = [v / np.sqrt((v.T @ G0 @ v)) for v in sp_vecs] + return sp_vecs +