pyerrors.mpm

View Source
 0import numpy as np
 1import scipy.linalg
 2from .obs import Obs
 3from .linalg import svd, eig
 4
 5
 6def matrix_pencil_method(corrs, k=1, p=None, **kwargs):
 7    """Matrix pencil method to extract k energy levels from data
 8
 9    Implementation of the matrix pencil method based on
10    eq. (2.17) of Y. Hua, T. K. Sarkar, IEEE Trans. Acoust. 38, 814-824 (1990)
11
12    Parameters
13    ----------
14    data : list
15        can be a list of Obs for the analysis of a single correlator, or a list of lists
16        of Obs if several correlators are to analyzed at once.
17    k : int
18        Number of states to extract (default 1).
19    p : int
20        matrix pencil parameter which filters noise. The optimal value is expected between
21        len(data)/3 and 2*len(data)/3. The computation is more expensive the closer p is
22        to len(data)/2 but could possibly suppress more noise (default len(data)//2).
23    """
24    if isinstance(corrs[0], Obs):
25        data = [corrs]
26    else:
27        data = corrs
28
29    lengths = [len(d) for d in data]
30    if lengths.count(lengths[0]) != len(lengths):
31        raise Exception('All datasets have to have the same length.')
32
33    data_sets = len(data)
34    n_data = len(data[0])
35
36    if p is None:
37        p = max(n_data // 2, k)
38    if n_data <= p:
39        raise Exception('The pencil p has to be smaller than the number of data samples.')
40    if p < k or n_data - p < k:
41        raise Exception('Cannot extract', k, 'energy levels with p=', p, 'and N-p=', n_data - p)
42
43    # Construct the hankel matrices
44    matrix = []
45    for n in range(data_sets):
46        matrix.append(scipy.linalg.hankel(data[n][:n_data - p], data[n][n_data - p - 1:]))
47    matrix = np.array(matrix)
48    # Construct y1 and y2
49    y1 = np.concatenate(matrix[:, :, :p])
50    y2 = np.concatenate(matrix[:, :, 1:])
51    # Apply SVD to y2
52    u, s, vh = svd(y2, **kwargs)
53    # Construct z from y1 and SVD of y2, setting all singular values beyond the kth to zero
54    z = np.diag(1. / s[:k]) @ u[:, :k].T @ y1 @ vh.T[:, :k]
55    # Return the sorted logarithms of the real eigenvalues as Obs
56    energy_levels = np.log(np.abs(eig(z, **kwargs)))
57    return sorted(energy_levels, key=lambda x: abs(x.value))
#   def matrix_pencil_method(corrs, k=1, p=None, **kwargs):
View Source
 7def matrix_pencil_method(corrs, k=1, p=None, **kwargs):
 8    """Matrix pencil method to extract k energy levels from data
 9
10    Implementation of the matrix pencil method based on
11    eq. (2.17) of Y. Hua, T. K. Sarkar, IEEE Trans. Acoust. 38, 814-824 (1990)
12
13    Parameters
14    ----------
15    data : list
16        can be a list of Obs for the analysis of a single correlator, or a list of lists
17        of Obs if several correlators are to analyzed at once.
18    k : int
19        Number of states to extract (default 1).
20    p : int
21        matrix pencil parameter which filters noise. The optimal value is expected between
22        len(data)/3 and 2*len(data)/3. The computation is more expensive the closer p is
23        to len(data)/2 but could possibly suppress more noise (default len(data)//2).
24    """
25    if isinstance(corrs[0], Obs):
26        data = [corrs]
27    else:
28        data = corrs
29
30    lengths = [len(d) for d in data]
31    if lengths.count(lengths[0]) != len(lengths):
32        raise Exception('All datasets have to have the same length.')
33
34    data_sets = len(data)
35    n_data = len(data[0])
36
37    if p is None:
38        p = max(n_data // 2, k)
39    if n_data <= p:
40        raise Exception('The pencil p has to be smaller than the number of data samples.')
41    if p < k or n_data - p < k:
42        raise Exception('Cannot extract', k, 'energy levels with p=', p, 'and N-p=', n_data - p)
43
44    # Construct the hankel matrices
45    matrix = []
46    for n in range(data_sets):
47        matrix.append(scipy.linalg.hankel(data[n][:n_data - p], data[n][n_data - p - 1:]))
48    matrix = np.array(matrix)
49    # Construct y1 and y2
50    y1 = np.concatenate(matrix[:, :, :p])
51    y2 = np.concatenate(matrix[:, :, 1:])
52    # Apply SVD to y2
53    u, s, vh = svd(y2, **kwargs)
54    # Construct z from y1 and SVD of y2, setting all singular values beyond the kth to zero
55    z = np.diag(1. / s[:k]) @ u[:, :k].T @ y1 @ vh.T[:, :k]
56    # Return the sorted logarithms of the real eigenvalues as Obs
57    energy_levels = np.log(np.abs(eig(z, **kwargs)))
58    return sorted(energy_levels, key=lambda x: abs(x.value))

Matrix pencil method to extract k energy levels from data

Implementation of the matrix pencil method based on eq. (2.17) of Y. Hua, T. K. Sarkar, IEEE Trans. Acoust. 38, 814-824 (1990)

Parameters
  • data (list): can be a list of Obs for the analysis of a single correlator, or a list of lists of Obs if several correlators are to analyzed at once.
  • k (int): Number of states to extract (default 1).
  • p (int): matrix pencil parameter which filters noise. The optimal value is expected between len(data)/3 and 2*len(data)/3. The computation is more expensive the closer p is to len(data)/2 but could possibly suppress more noise (default len(data)//2).