jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def lhn(G, c=0.9, remove_neighbors=False, inv_method=0):
  # TODO: remove sim scores b2n neighbors when remove_neighbors==True
  """Return the LHN similarity between nodes

  Parameters
  -----------
  G : graph
    A NetworkX graph
  remove_neighbors: boolean
    if true, only return LHN similarity of non-neighbor nodes

  Returns
  -------
  S: matrix of similarity
  nodelist: the node ids

  Examples
  --------
  >>> G=nx.Graph()
  >>> G.add_edges_from([(0,7), (0,1), (0,2), (0,3), (1,4), (2,4), (3,4), (4,5), (4,6)])
  >>> networkx_addon.similarity.lhn(G)

  Notes
  -----

  References
  ----------
  """
  if type(G) == nx.MultiGraph or type(G) == nx.MultiDiGraph:
    raise Exception("lhn() not defined for graphs with multiedges.")

  if G.is_directed():
    raise Exception("lhn() not defined for directed graphs.")

  A = nx.adjacency_matrix(G, nodelist=G.nodes(), weight=None)
  w, v = numpy.linalg.eigh(A)
  lambda1 = max([abs(x) for x in w])
  I = numpy.eye(A.shape[0])
  S = None
  if inv_method == 1:
    S = numpy.linalg.pinv(I - c/lambda1 * A)
  elif inv_method == 2:
    S = numpy.linalg.inv(I - c/lambda1 * A)
  else:
    S = numpy.linalg.pinv(I - c/lambda1 * A)
  deg = numpy.array(sum(A)).reshape(-1,)
  for i in range(S.shape[0]):
    for j in range(S.shape[1]):
      S[i,j] /= (deg[i]*deg[j])
  return S, G.nodes()
//  [python]
def lhn(G, c=0.9, remove_neighbors=False, inv_method=0):
  # TODO: remove sim scores b2n neighbors when remove_neighbors==True
  """Return the LHN similarity between nodes

  Parameters
  -----------
  G : graph
    A NetworkX graph
  remove_neighbors: boolean
    if true, only return LHN similarity of non-neighbor nodes

  Returns
  -------
  S: matrix of similarity
  nodelist: the node ids

  Examples
  --------
  >>> G=nx.Graph()
  >>> G.add_edges_from([(0,7), (0,1), (0,2), (0,3), (1,4), (2,4), (3,4), (4,5), (4,6)])
  >>> networkx_addon.similarity.lhn(G)

  Notes
  -----

  References
  ----------
  """
  if type(G) == nx.MultiGraph or type(G) == nx.MultiDiGraph:
    raise Exception("lhn() not defined for graphs with multiedges.")

  if G.is_directed():
    raise Exception("lhn() not defined for directed graphs.")

  A = nx.adjacency_matrix(G, nodelist=G.nodes(), weight=None)
  w, v = numpy.linalg.eigh(A)
  lambda1 = max([abs(x) for x in w])
  I = numpy.eye(A.shape[0])
  S = None
  if inv_method == 1:
    S = scipy.linalg.pinv(I - c/lambda1 * A)
  elif inv_method == 2:
    S = numpy.linalg.inv(I - c/lambda1 * A)
  else:
    S = numpy.linalg.pinv(I - c/lambda1 * A)
  deg = numpy.array(sum(A)).reshape(-1,)
  for i in range(S.shape[0]):
    for j in range(S.shape[1]):
      S[i,j] /= (deg[i]*deg[j])
  return S, G.nodes()
//  [python]
def mlr(self,x,y):
        """Multiple linear regression fit of the columns of matrix x 
        (dependent variables) to constituent vector y (independent variables)
        
        order -     order of a smoothing polynomial, which can be included 
                    in the set of independent variables. If order is
                    not specified, no background will be included.
        b -         fit coeffs
        f -         fit result (m x 1 column vector)
        r -         residual   (m x 1 column vector)
        """
        
        if self.order > 0:
            s=scipy.ones((len(y),1))
            for j in range(self.order):
                s=scipy.concatenate((s,(scipy.arange(0,1+(1.0/(len(y)-1)),1.0/(len(y)-1))**j)[:,nA]),1)
            X=scipy.concatenate((x, s),1)
        else:
            X = x
        
        #calc fit b=fit coefficients
        b = scipy.dot(scipy.dot(scipy.linalg.inv(scipy.dot(scipy.transpose(X),X)),scipy.transpose(X)),y)
        f = scipy.dot(X,b)
        r = y - f

        return b,f,r
//  [python]
def mlr(self,x,y):
        """Multiple linear regression fit of the columns of matrix x 
        (dependent variables) to constituent vector y (independent variables)
        
        order -     order of a smoothing polynomial, which can be included 
                    in the set of independent variables. If order is
                    not specified, no background will be included.
        b -         fit coeffs
        f -         fit result (m x 1 column vector)
        r -         residual   (m x 1 column vector)
        """
        
        if self.order > 0:
            s=scipy.ones((len(y),1))
            for j in range(self.order):
                s=scipy.concatenate((s,(scipy.arange(0,1+(1.0/(len(y)-1)),1.0/(len(y)-1))**j)[:,nA]),1)
            X=scipy.concatenate((x, s),1)
        else:
            X = x
        
        #calc fit b=fit coefficients
        b = scipy.dot(scipy.dot(scipy.linalg.pinv(scipy.dot(scipy.transpose(X),X)),scipy.transpose(X)),y)
        f = scipy.dot(X,b)
        r = y - f

        return b,f,r
//  [python]
def niqe(inputImgData, patch_size=96):
    if isinstance(inputImgData, str):
        #inputImgData = np.array(Image.open(inputImgData).convert('LA'))[:,:,0] #[:,512:1024,0]
        try:
            inputImgData = cv2.cvtColor(cv2.imread(inputImgData), cv2.COLOR_RGB2LAB)[:,512:1024,0]#[:,:,0]

        except:
            return None
    # TODO: memoize

    M, N = inputImgData.shape

    # assert C == 1, "niqe called with videos containing %d channels. Please supply only the luminance channel" % (C,)
    assert M > (patch_size*2+1), "niqe called with small frame size, requires > 192x192 resolution video using current training parameters"
    assert N > (patch_size*2+1), "niqe called with small frame size, requires > 192x192 resolution video using current training parameters"


    feats = get_patches_test_features(inputImgData, patch_size)
    sample_mu = np.mean(feats, axis=0)
    sample_cov = np.cov(feats.T)

    X = sample_mu - pop_mu
    covmat = ((pop_cov+sample_cov)/2.0)
    pinvmat = np.linalg.pinv(covmat)
    niqe_score = np.sqrt(np.dot(np.dot(X, pinvmat), X))
    return niqe_score
//  [python]
def niqe(inputImgData, patch_size=96):
    if isinstance(inputImgData, str):
        #inputImgData = np.array(Image.open(inputImgData).convert('LA'))[:,:,0] #[:,512:1024,0]
        try:
            inputImgData = cv2.cvtColor(cv2.imread(inputImgData), cv2.COLOR_RGB2LAB)[:,512:1024,0]#[:,:,0]

        except:
            return None
    # TODO: memoize

    M, N = inputImgData.shape

    # assert C == 1, "niqe called with videos containing %d channels. Please supply only the luminance channel" % (C,)
    assert M > (patch_size*2+1), "niqe called with small frame size, requires > 192x192 resolution video using current training parameters"
    assert N > (patch_size*2+1), "niqe called with small frame size, requires > 192x192 resolution video using current training parameters"


    feats = get_patches_test_features(inputImgData, patch_size)
    sample_mu = np.mean(feats, axis=0)
    sample_cov = np.cov(feats.T)

    X = sample_mu - pop_mu
    covmat = ((pop_cov+sample_cov)/2.0)
    pinvmat = scipy.linalg.pinv(covmat)
    niqe_score = np.sqrt(np.dot(np.dot(X, pinvmat), X))
    return niqe_score
//  [python]
def affine(X, Y):
    """ find affine transformation

    Parameters
    ----------

    X  : np.array
        3xN
    Y
        3xN

    Returns
    -------

    A : np.array
        3x3
    B : np.array
        3x1

    Notes
    -----

    Given X and Y find the affine transformation

    Y = A X + B

    """

    B = Y[:, 0][:, np.newaxis]
    Yc = Y - B
    pX = la.pinv(X)
    A = np.dot(Yc, pX)
    return(A, B)
//  [python]
def vectorize_expvals(
    num_qubits: int,
    expvals: Dict,
    covars: Optional[Dict] = None,
    distribute_with_covars: Optional[bool] = False,
    zz_flag: Optional[bool] = False,
) -> Tuple[np.ndarray, np.ndarray]:
    '''Convert a set of expectation values to a vector in a fixed basis.

    Args:
        num_qubits [int]: number of qubits in operator
        expvals [dict]: indexed by QubitOperators, contains the corresponding
            expectation value estimates Trace[rho * O]
        covars [dict[dict]]: covariance matrix in dictionary form
        distribute_with_covars [bool]: Whether to distribute term coefficients
            to minimise the covariance of the resulting sum based on the given
            covariances or just on the term sizes. This former is in
            principle optimal, but in practice appears unstable.
        zz_flag [bool]: whether or not this Hamiltonian contains ZZ terms
    '''
    fixed_operator_order = list(expvals.keys())
    trace_vector = np.array([expvals[op] for op in fixed_operator_order])

    num_operators = len(fixed_operator_order)
    if zz_flag:
        num_basis_vectors = num_qubits**2
    else:
        num_basis_vectors = (num_qubits + 1) * num_qubits // 2

    overlap_matrix = np.zeros([num_operators, num_basis_vectors])
    for op_index, op in enumerate(fixed_operator_order):
        coeff_list = indexing_function(num_qubits, QubitOperator(op))
        for index, coeff in coeff_list:
            overlap_matrix[op_index, index] += coeff

    if covars is None:
        inv_matrix = np.linalg.pinv(overlap_matrix.T @ overlap_matrix)
        expval_vec = trace_vector.T @ overlap_matrix @ inv_matrix
        new_covariance_matrix = None
    else:
        covar_matrix = np.array(
            [
                [covars[op][op2] if op2 in covars[op] else 0 for op2 in fixed_operator_order]
                for op in fixed_operator_order
            ]
        )
        covar_matrix = covar_matrix + np.identity(len(covar_matrix)) * 1e-10
        if distribute_with_covars:
            covar_matrix_inv = np.linalg.inv(covar_matrix)
            inv_matrix = np.linalg.pinv(overlap_matrix.T @ covar_matrix_inv @ overlap_matrix)
            conversion_matrix = covar_matrix_inv @ overlap_matrix @ inv_matrix
        else:
            inv_matrix = np.linalg.pinv(overlap_matrix.T @ overlap_matrix)
            conversion_matrix = overlap_matrix @ inv_matrix
        expval_vec = trace_vector.T @ conversion_matrix

        new_covariance_matrix = conversion_matrix.T @ covar_matrix @ conversion_matrix
    return expval_vec, new_covariance_matrix
//  [python]
def vectorize_expvals(
    num_qubits: int,
    expvals: Dict,
    covars: Optional[Dict] = None,
    distribute_with_covars: Optional[bool] = False,
    zz_flag: Optional[bool] = False,
) -> Tuple[np.ndarray, np.ndarray]:
    '''Convert a set of expectation values to a vector in a fixed basis.

    Args:
        num_qubits [int]: number of qubits in operator
        expvals [dict]: indexed by QubitOperators, contains the corresponding
            expectation value estimates Trace[rho * O]
        covars [dict[dict]]: covariance matrix in dictionary form
        distribute_with_covars [bool]: Whether to distribute term coefficients
            to minimise the covariance of the resulting sum based on the given
            covariances or just on the term sizes. This former is in
            principle optimal, but in practice appears unstable.
        zz_flag [bool]: whether or not this Hamiltonian contains ZZ terms
    '''
    fixed_operator_order = list(expvals.keys())
    trace_vector = np.array([expvals[op] for op in fixed_operator_order])

    num_operators = len(fixed_operator_order)
    if zz_flag:
        num_basis_vectors = num_qubits**2
    else:
        num_basis_vectors = (num_qubits + 1) * num_qubits // 2

    overlap_matrix = np.zeros([num_operators, num_basis_vectors])
    for op_index, op in enumerate(fixed_operator_order):
        coeff_list = indexing_function(num_qubits, QubitOperator(op))
        for index, coeff in coeff_list:
            overlap_matrix[op_index, index] += coeff

    if covars is None:
        inv_matrix = scipy.linalg.pinv(overlap_matrix.T @ overlap_matrix)
        expval_vec = trace_vector.T @ overlap_matrix @ inv_matrix
        new_covariance_matrix = None
    else:
        covar_matrix = np.array(
            [
                [covars[op][op2] if op2 in covars[op] else 0 for op2 in fixed_operator_order]
                for op in fixed_operator_order
            ]
        )
        covar_matrix = covar_matrix + np.identity(len(covar_matrix)) * 1e-10
        if distribute_with_covars:
            covar_matrix_inv = np.linalg.inv(covar_matrix)
            inv_matrix = scipy.linalg.pinv(overlap_matrix.T @ covar_matrix_inv @ overlap_matrix)
            conversion_matrix = covar_matrix_inv @ overlap_matrix @ inv_matrix
        else:
            inv_matrix = scipy.linalg.pinv(overlap_matrix.T @ overlap_matrix)
            conversion_matrix = overlap_matrix @ inv_matrix
        expval_vec = trace_vector.T @ conversion_matrix

        new_covariance_matrix = conversion_matrix.T @ covar_matrix @ conversion_matrix
    return expval_vec, new_covariance_matrix
//  [python]
def continuous_to_discrete(a, b, sampling_rate):
    """
    Converts a continuous-time system to its equivalent discrete-time version.

    Parameters
    ----------
    a : (N, N) array of floats
        State variable coefficients describing the continuous-time system.
    b : (N,) or (N, 1) array of floats
        Constant coefficients describing the continuous-time system. Can be
        either a rank-1 array or a rank-2 array of shape (N, 1).
    sampling_rate : float
        Rate in Hz at which the continuous-time system is to be sampled.

    Returns
    -------
    phi : (N, N) array of floats
        Variable coefficients describing the discrete-time system.
    gamma : (N,) or (N, 1) array of floats
        Constant coefficients describing the discrete-time system. Shape of
        this output maintains the shape passed as `b`.

    """
    a = a.astype(float)
    b = b.astype(float)

    phi = scipy.linalg.expm(a * sampling_rate)

    a_pinv = np.linalg.pinv(a)

    gamma = np.dot(np.dot(a_pinv, phi - np.eye(a.shape[0])), b)

    return phi, gamma
//  [python]
def continuous_to_discrete(a, b, sampling_rate):
    """
    Converts a continuous-time system to its equivalent discrete-time version.

    Parameters
    ----------
    a : (N, N) array of floats
        State variable coefficients describing the continuous-time system.
    b : (N,) or (N, 1) array of floats
        Constant coefficients describing the continuous-time system. Can be
        either a rank-1 array or a rank-2 array of shape (N, 1).
    sampling_rate : float
        Rate in Hz at which the continuous-time system is to be sampled.

    Returns
    -------
    phi : (N, N) array of floats
        Variable coefficients describing the discrete-time system.
    gamma : (N,) or (N, 1) array of floats
        Constant coefficients describing the discrete-time system. Shape of
        this output maintains the shape passed as `b`.

    """
    a = a.astype(float)
    b = b.astype(float)

    phi = scipy.linalg.expm(a * sampling_rate)

    a_pinv = scipy.linalg.pinv(a)

    gamma = np.dot(np.dot(a_pinv, phi - np.eye(a.shape[0])), b)

    return phi, gamma
//  [python]
def fit(self, data, **kwargs):
        r""" Fit this estimator instance onto data.

        Parameters
        ----------
        data
            Input data, see :meth:`to_dataset <deeptime.util.types.to_dataset>` for options.
        **kwargs
            Kwargs, may contain lagtime.

        Returns
        -------
        self : EDMD
            Reference to self.
        """
        dataset = to_dataset(data, lagtime=kwargs.get("lagtime", None))
        x, y = dataset[:]
        n_data = x.shape[0]
        assert n_data == y.shape[0], "Trajectories for data and timelagged data must be of same length!"
        psi_x = self.basis(x).T
        psi_y = self.basis(y).T

        cov_00 = (1/x.shape[0]) * psi_x @ psi_x.T
        cov_0t = (1/x.shape[0]) * psi_x @ psi_y.T

        if self.operator != 'koopman':
            cov_0t = cov_0t.T

        m_edmd = s.pinv(cov_00) @ cov_0t
        eig_val, eig_vec = eigs(m_edmd, self.n_eigs)
        eig_val, eig_vec = sort_eigs(eig_val, eig_vec, order='lexicographic')
        self._model = EDMDModel(m_edmd, basis=self.basis, eigenvalues=eig_val, modes=eig_vec.T)
        return self
//  [python]
def fit(self, data, **kwargs):
        r""" Fit this estimator instance onto data.

        Parameters
        ----------
        data
            Input data, see :meth:`to_dataset <deeptime.util.types.to_dataset>` for options.
        **kwargs
            Kwargs, may contain lagtime.

        Returns
        -------
        self : EDMD
            Reference to self.
        """
        dataset = to_dataset(data, lagtime=kwargs.get("lagtime", None))
        x, y = dataset[:]
        n_data = x.shape[0]
        assert n_data == y.shape[0], "Trajectories for data and timelagged data must be of same length!"
        psi_x = self.basis(x).T
        psi_y = self.basis(y).T

        cov_00 = (1/x.shape[0]) * psi_x @ psi_x.T
        cov_0t = (1/x.shape[0]) * psi_x @ psi_y.T

        if self.operator != 'koopman':
            cov_0t = cov_0t.T

        m_edmd = scipy.linalg.pinv(cov_00) @ cov_0t
        eig_val, eig_vec = eigs(m_edmd, self.n_eigs)
        eig_val, eig_vec = sort_eigs(eig_val, eig_vec, order='lexicographic')
        self._model = EDMDModel(m_edmd, basis=self.basis, eigenvalues=eig_val, modes=eig_vec.T)
        return self
//  [python]
def dlqr(self):
        '''
        求解离散时间lqr控制器
        '''
        # 尝试解出ricatti方程
        X = self.solve_DARE(self.A, self.B, self.Q, self.R)

        # 计算LQR增益
        K = la.pinv(self.R + self.B.T * X * self.B) * (self.B.T * X * self.A)

        return K
//  [python]
def solve_DARE(self, A, B, Q, R):
        '''
        求解离散时间-代数黎卡提方程
        '''
        P = Q
        maxiter = 200
        eps = 0.01

        for _ in range(maxiter):
            Pn = A.T * P * A - A.T * P * B * la.pinv(R + B.T * P * B) * B.T * P * A + Q
            if (abs(Pn - P)).max() < eps:
                P = Pn
                break
            P = Pn
        return Pn
//  [python]
def regressOut(Y, X, return_b=False):
    """
    regresses out X from Y
    """
    Xd = s.pinv(X)
    b = Xd.dot(Y)
    Y_out = Y-X.dot(b)
    if return_b:
        return Y_out, b
    else:
        return Y_out
//  [python]
def regressOut(Y, X, return_b=False):
    """
    regresses out X from Y
    """
    Xd = la.pinv(X)
    b = Xd.dot(Y)
    Y_out = Y-X.dot(b)
    if return_b:
        return Y_out, b
    else:
        return Y_out
//  [python]
def cylmap(Y, r=0.0625, l=0.5):
    """ find affine transformation for a specific cylinder

    Parameters
    ----------

    Y
        3xN

    Returns
    -------

    A : np.array
        3x3
    B : np.array
        3x1

    Notes
    -----

    Y = A X + B

    """
    #X = np.array([[0,0,0],[0,0,-0.25],[0,0,0.25],[0.0625,0,0],[0,0.0625,0],[0.0625,0,0.25]]).T
    X = np.array([[0, 0, 0], [0, 0, -l / 2], [0, 0, l / 2],
                  [r, 0, 0], [0, r, 0], [r, 0, l / 2]]).T
    B = Y[:, 0][:, np.newaxis]
    Yc = Y - B
    pX = la.pinv(X)
    A = np.dot(Yc, pX)
    return(A, B)
//  [python]
def compute_sigma_squared_vector_covariances(sigma: Array, sigma_vector_covariances: Array) -> Array:
    """Use the delta method to transform the asymptotic covariance matrix of vech(sigma) into the asymptotic covariance
    matrix of vech(sigma * sigma') where sigma is a lower triangular Cholesky root of parameters. See Section 10.5.4 in
    the Handbook of Matrices (Lutkepohl and Lutkepohl).
    """
    if sigma_vector_covariances.size == 0:
        return sigma_vector_covariances

    k = sigma.shape[0]
    L = elimination_matrix(k)
    D = duplication_matrix(k)
    I = np.eye(k)
    jacobian = 2 * np.linalg.pinv(D) @ np.kron(sigma, I) @ L.T
    return jacobian @ sigma_vector_covariances @ jacobian.T
//  [python]
def compute_sigma_squared_vector_covariances(sigma: Array, sigma_vector_covariances: Array) -> Array:
    """Use the delta method to transform the asymptotic covariance matrix of vech(sigma) into the asymptotic covariance
    matrix of vech(sigma * sigma') where sigma is a lower triangular Cholesky root of parameters. See Section 10.5.4 in
    the Handbook of Matrices (Lutkepohl and Lutkepohl).
    """
    if sigma_vector_covariances.size == 0:
        return sigma_vector_covariances

    k = sigma.shape[0]
    L = elimination_matrix(k)
    D = duplication_matrix(k)
    I = np.eye(k)
    jacobian = 2 * scipy.linalg.pinv(D) @ np.kron(sigma, I) @ L.T
    return jacobian @ sigma_vector_covariances @ jacobian.T
//  [python]
def _ridge_smooth_inverse(D, alphas, fit_intercept=True, as_matrix=False):

    wsize = D.shape[:2]
    nD = D.shape[2]
    invC = np.zeros(wsize)
    for j in range(nD):
        invC += alphas[j] * D[:, :, j]

    if fit_intercept:
        Cprior = np.zeros_like(invC)
        try:
            Cprior[1:, 1:] = linalg.inv(invC[1:, 1:])
        except:
            Cprior[1:, 1:] = linalg.pinv(invC[1:, 1:])
    else:
        Cprior = linalg.pinv(invC)

    if as_matrix:
        Cprior = np.matrix(Cprior, copy=False)
        invC = np.matrix(invC, copy=False)

    return Cprior, invC
//  [python]
def optimize(self, mask):
        """
        Optimize unshimmed volume by varying current to each channel

        Args:
            mask (np.ndarray): 3d array of integers marking volume for optimization. Must be the same shape as
                                  unshimmed

        Returns:
            np.ndarray: Coefficients corresponding to the coil profiles that minimize the objective function.
                           The shape of the array returned has shape corresponding to the total number of channels
        """
        coil_mat, unshimmed_vec = self.get_coil_mat_and_unshimmed(mask)

        output = -1 * numpy.linalg.pinv(coil_mat) @ unshimmed_vec  # N x mV' @ mV'

        return output
//  [python]
def optimize(self, mask):
        """
        Optimize unshimmed volume by varying current to each channel

        Args:
            mask (np.ndarray): 3d array of integers marking volume for optimization. Must be the same shape as
                                  unshimmed

        Returns:
            np.ndarray: Coefficients corresponding to the coil profiles that minimize the objective function.
                           The shape of the array returned has shape corresponding to the total number of channels
        """
        coil_mat, unshimmed_vec = self.get_coil_mat_and_unshimmed(mask)

        output = -1 * scipy.linalg.pinv(coil_mat) @ unshimmed_vec  # N x mV' @ mV'

        return output
//  [python]
def ridge_evidence_optim(X, y, init_params=None, verbose=False):

    if init_params is None:
        init_params = np.asarray([10., 10.])

    N, p = X.shape

    # Precompute covariances and noise variance of OLS solution
    XX = np.dot(X.T, X)
    Xy = np.dot(X.T, y)
    yy = np.sum(y * y)
    I = np.eye(p)

    w0 = linalg.solve(XX + 10*I, Xy, sym_pos=False)
    nv = np.sum((y - np.dot(X, w0))**2) / N
    init_params[0] = nv

    other = [XX, Xy, yy]

    # Call optimization routine
    fun = _ridge_evidence_fun_grad
    x0 = init_params
    fprime = None
    args = (X, y, verbose, other)
    bounds = [(1e-6, 1e6), (1e-6, 1e6)]

    print("x0:", x0)
    res = optimize.fmin_tnc(fun, x0, fprime=fprime, args=args,
                            approx_grad=0, bounds=bounds, epsilon=1e-08)

    opt_params = res[0]
    nv = opt_params[0]
    alpha = opt_params[1]

    if verbose:
        print("nv: %0.3f | alpha: %0.3f" % (nv, alpha))

    # Compute final quantities
    Cprior = 1./alpha * I
    invC = alpha * I
    SS = linalg.pinv2(XX/nv + invC)
    mu = np.dot(SS,  Xy) / nv

    return mu, SS, nv, Cprior, alpha
//  [python]
def ridge_evidence_optim(X, y, init_params=None, verbose=False):

    if init_params is None:
        init_params = np.asarray([10., 10.])

    N, p = X.shape

    # Precompute covariances and noise variance of OLS solution
    XX = np.dot(X.T, X)
    Xy = np.dot(X.T, y)
    yy = np.sum(y * y)
    I = np.eye(p)

    w0 = linalg.solve(XX + 10*I, Xy, sym_pos=False)
    nv = np.sum((y - np.dot(X, w0))**2) / N
    init_params[0] = nv

    other = [XX, Xy, yy]

    # Call optimization routine
    fun = _ridge_evidence_fun_grad
    x0 = init_params
    fprime = None
    args = (X, y, verbose, other)
    bounds = [(1e-6, 1e6), (1e-6, 1e6)]

    print("x0:", x0)
    res = optimize.fmin_tnc(fun, x0, fprime=fprime, args=args,
                            approx_grad=0, bounds=bounds, epsilon=1e-08)

    opt_params = res[0]
    nv = opt_params[0]
    alpha = opt_params[1]

    if verbose:
        print("nv: %0.3f | alpha: %0.3f" % (nv, alpha))

    # Compute final quantities
    Cprior = 1./alpha * I
    invC = alpha * I
    SS = linalg.pinv(XX/nv + invC)
    mu = np.dot(SS,  Xy) / nv

    return mu, SS, nv, Cprior, alpha
//  [python]
def getK_GCN(self):
        A = preprocess_graph(self.data._A_obs[self.data.nodes_AB_all,:][:,self.data.nodes_AB_all]).tocsr()#1.add self-loop 2.sys-normalize
        X = row_normalize(self.data._X_obs[self.data.nodes_AB_all]).tocsr()
        X_bar = A.dot(A).dot(X).tocsr()
        X_bar_l = X_bar[self.data.split_train,:]
        tmp = X_bar_l.T.dot(X_bar_l)
        tmp = sp.csr_matrix(np.linalg.pinv(tmp.toarray()+ self.gcnL2*np.identity(tmp.shape[0])))
        tmp = tmp.dot(X_bar_l.T)
        K = X_bar.dot(tmp)[self.data.split_unlabeled,:].toarray()
        return K
//  [python]
def getK_GCN(self):
        A = preprocess_graph(self.data._A_obs[self.data.nodes_AB_all,:][:,self.data.nodes_AB_all]).tocsr()#1.add self-loop 2.sys-normalize
        X = row_normalize(self.data._X_obs[self.data.nodes_AB_all]).tocsr()
        X_bar = A.dot(A).dot(X).tocsr()
        X_bar_l = X_bar[self.data.split_train,:]
        tmp = X_bar_l.T.dot(X_bar_l)
        tmp = sp.csr_matrix(scipy.linalg.pinv(tmp.toarray()+ self.gcnL2*np.identity(tmp.shape[0])))
        tmp = tmp.dot(X_bar_l.T)
        K = X_bar.dot(tmp)[self.data.split_unlabeled,:].toarray()
        return K
//  [python]
def _ridge_evidence_fun_grad(theta, X, y, verbose, other):

    nv = theta[0]
    alpha = theta[1]

    XX, Xy, yy = other

    N, p = X.shape
    I = np.eye(p)

    # Prior covariance matrix for current parameter setting
    Cprior = 1./alpha * I
    Cprior[0, 0] = 0

    invCprior = alpha * I
    invCprior[0, 0] = 0

    # Posterior covariance and mean
    SS = linalg.pinv(XX/nv + invCprior)
    mu = np.dot(SS, Xy)/nv

    # (1) Compute log-evidence
    term1 = .5*(fast_logdet(2*np.pi*SS) - p*np.log(2*np.pi/alpha)
                - p*np.log(2*np.pi*nv))
    term2 = -.5*(yy/nv - np.dot(Xy.T, np.dot(SS, Xy))/nv**2)
    logE = term1 + term2

    # Gradient with respect to the ridge parameter
#    dAlpha = .5 * np.trace(1./alpha*I + SS + np.outer(mu, mu))
    dAlpha = p/(2*alpha) - .5*np.sum(mu*mu) - .5*np.trace(SS)

    # Gradient with respect to the noise variance
    SSinvC = np.dot(SS, invCprior)
    rss = yy - 2*np.dot(mu.T, Xy) + np.dot(mu.T, XX).dot(mu)
    dNsevar = -N/nv + np.trace(I - SSinvC)/nv + rss/nv**2

    dEE = np.array([dNsevar.item(), dAlpha])

    if verbose:
        print("-logE: %0.3f | nv: %0.3f | alpha: %0.3f" % (-logE, nv, alpha))

    return -logE, -dEE
//  [python]
def _ridge_smooth_fun_grad(theta, X, y, D, verbose, other):

    nv = theta[0]
    alphas = theta[1:]

    XX, Xy, yy, fit_intercept = other

    N, p = X.shape
    nD = D.shape[2]
    I = np.eye(p)

    # Prior covariance matrix for current parameter setting
    Cprior, invC = _ridge_smooth_inverse(D, alphas,
                                         fit_intercept=fit_intercept)

    # Posterior covariance and mean
    SS = s.pinv(XX/nv + invC)
    mu = np.dot(SS, Xy)/nv

    # Compute log-evidence
    term1 = .5*(fast_logdet(2*np.pi*SS) - p*np.log(2*np.pi*nv)
                - p*np.log(2*np.pi) - 1./fast_logdet(invC))
    term2 = -.5*(yy/nv - np.dot(Xy.T, np.dot(SS, Xy))/nv**2)
    logE = term1 + term2

    # Derivative with respect to covariance hyperparameters
    dAlphas = np.zeros((nD,))
    for i in range(nD):
        A = Cprior - SS - np.outer(mu, mu)
        dAlphas[i] = .5*np.trace(np.dot(A, D[:, :, i]))

    # Gradient with respect to the noise variance
    SSinvC = np.dot(SS, invC)
    rss = yy - 2*np.dot(mu.T, Xy) + np.dot(mu.T, XX).dot(mu)
    dNsevar = -N/nv + np.trace(I - SSinvC)/nv + rss/nv**2

    dEE = np.append(dNsevar.item(), dAlphas)

    if verbose:
        ss =("-logE: %0.3f | nv: %0.3f | alphas: (" % (-logE, nv))
        for alpha in alphas:
            ss += ("%0.3g, " % alpha)
        print(s[:-2] + ")")

    return -logE, -dEE
//  [python]
def _ridge_smooth_fun_grad(theta, X, y, D, verbose, other):

    nv = theta[0]
    alphas = theta[1:]

    XX, Xy, yy, fit_intercept = other

    N, p = X.shape
    nD = D.shape[2]
    I = np.eye(p)

    # Prior covariance matrix for current parameter setting
    Cprior, invC = _ridge_smooth_inverse(D, alphas,
                                         fit_intercept=fit_intercept)

    # Posterior covariance and mean
    SS = linalg.pinv(XX/nv + invC)
    mu = np.dot(SS, Xy)/nv

    # Compute log-evidence
    term1 = .5*(fast_logdet(2*np.pi*SS) - p*np.log(2*np.pi*nv)
                - p*np.log(2*np.pi) - 1./fast_logdet(invC))
    term2 = -.5*(yy/nv - np.dot(Xy.T, np.dot(SS, Xy))/nv**2)
    logE = term1 + term2

    # Derivative with respect to covariance hyperparameters
    dAlphas = np.zeros((nD,))
    for i in range(nD):
        A = Cprior - SS - np.outer(mu, mu)
        dAlphas[i] = .5*np.trace(np.dot(A, D[:, :, i]))

    # Gradient with respect to the noise variance
    SSinvC = np.dot(SS, invC)
    rss = yy - 2*np.dot(mu.T, Xy) + np.dot(mu.T, XX).dot(mu)
    dNsevar = -N/nv + np.trace(I - SSinvC)/nv + rss/nv**2

    dEE = np.append(dNsevar.item(), dAlphas)

    if verbose:
        ss =("-logE: %0.3f | nv: %0.3f | alphas: (" % (-logE, nv))
        for alpha in alphas:
            ss += ("%0.3g, " % alpha)
        print(s[:-2] + ")")

    return -logE, -dEE
//  [python]
def esprit(CovMat,L,N):
    # CovMat is the signal covariance matrix, L is the number of sources, N is the number of antennas
    _,U = LA.eig(CovMat)
    S = U[:,0:L]
    Phi = LA.pinv(S[0:N-1]) @ S[1:N] # the original array is divided into two subarrays [0,1,...,N-2] and [1,2,...,N-1]
    eigs,_ = LA.eig(Phi)
    DoAsESPRIT = np.arcsin(np.angle(eigs)/np.pi)
    return DoAsESPRIT
//  [python]
def _construct_gateset_gram(self) -> dict:
        r"""Construct the Gram matrix transformed gate set :math:`\hat{\mathcal{G}}`.

        In the notation of [G15], the Gram matrix transformed gate set :math:`\hat{\mathcal{G}}` is
        defined in Eqs. (3.21)-(3.23) and has the following form

        .. math::

            \hat{\mathcal{G}} = \{ |\hat{\rho}\rangle\!\rangle, \langle\!\langle\hat{E}\vert,
                                    \hat{G}_1, \cdots, \hat{G}_K\}.

        where the quantities are obtained from the experimentally accessible gate set :math:`\tilde{\mathcal{G}}`
        using the Gram matrix :math:`g` as follows:

        .. math::

            \begin{aligned}
                \begin{align*}
                    \hat{G}_k &= g^{-1}\tilde{G}_k \\
                    \vert\hat{\rho}\rangle\!\rangle &= g^{-1}|\tilde{\rho}\rangle\!\rangle \\
                    \langle\!\langle\hat{E}\vert &= \langle\!\langle\tilde{E}\vert
                \end{align*}
            \end{aligned}

        .. note::

            We emphasize that the Gram matrix transformed gate set does not contain the 'null' gate.

        :return: dict, a dictionary that records the Gram matrix transformed gate set
        """
        # Load the experimentally accessible gate set and the Gram matrix
        gateset_exp = deepcopy(self._gateset_exp)
        g = gateset_exp[GateSet.NULL_GATE_NAME]

        gateset_gram: Dict[str, np.ndarray] = dict()
        # Construct the Gram matrix transformed quantum state and measurement
        gateset_gram.update({"rho": la.pinv(g) @ gateset_exp["rho"]})
        gateset_gram.update({"E": gateset_exp["E"]})
        gateset_exp.pop("rho", None)
        gateset_exp.pop("E", None)
        # delete the 'null' gate so that the Gram matrix transformed gate set does not contain it
        gateset_exp.pop(GateSet.NULL_GATE_NAME, None)

        # Construct the Gram matrix transformed quantum gates, which does not include the 'null' gate
        for key, val in gateset_exp.items():
            gateset_gram.update({key: la.pinv(g) @ val})

        # Record the Gram matrix transformed gate set
        self._optimized_result.update({"gateset gram": gateset_gram})

        return gateset_gram
//  [python]
def analyze_model_resolution_matrix(G, num_obs, outdir):
    """
    Simply analyze the resolution matrix R (Menke, 1989)
    Before leveling offsets have been added.
    """
    # Show big-G matrix for all times, all data
    plt.figure(figsize=(12, 8), dpi=300)
    plt.imshow(G, vmin=-0.02, vmax=0.02, aspect=1)
    plt.savefig(os.path.join(outdir, "G_resolution.png"))

    # Model Resolution Matrix
    Ggi = np.array(np.linalg.pinv(G))  # Replace all smoothing with zeros for second half of this expression
    G_nosmoothing = G.copy()
    G_nosmoothing[num_obs:, :] = 0
    Rmatrix = np.dot(Ggi, G_nosmoothing)  # R matrix

    # Model Covariance values
    covb_slip = np.dot(Ggi, Ggi.T)
    sig_slipb = np.sqrt(np.diag(covb_slip))

    # Viewing the diagonal elements of R (might be helpful?)
    plt.figure()
    plt.plot(np.diag(Rmatrix))
    plt.savefig(os.path.join(outdir, 'model_resolution_diagonal.png'))

    # Viewing the total picture of R: shows the model resolution along the diagonal.
    plt.figure(figsize=(12, 8), dpi=300)
    plt.imshow(Rmatrix, aspect=1)
    plt.colorbar()
    plt.savefig(os.path.join(outdir, "Rmatrix.png"))
    return np.diag(Rmatrix), sig_slipb
//  [python]
def analyze_model_resolution_matrix(G, num_obs, outdir):
    """
    Simply analyze the resolution matrix R (Menke, 1989)
    Before leveling offsets have been added.
    """
    # Show big-G matrix for all times, all data
    plt.figure(figsize=(12, 8), dpi=300)
    plt.imshow(G, vmin=-0.02, vmax=0.02, aspect=1)
    plt.savefig(os.path.join(outdir, "G_resolution.png"))

    # Model Resolution Matrix
    Ggi = np.array(scipy.linalg.pinv(G))  # Replace all smoothing with zeros for second half of this expression
    G_nosmoothing = G.copy()
    G_nosmoothing[num_obs:, :] = 0
    Rmatrix = np.dot(Ggi, G_nosmoothing)  # R matrix

    # Model Covariance values
    covb_slip = np.dot(Ggi, Ggi.T)
    sig_slipb = np.sqrt(np.diag(covb_slip))

    # Viewing the diagonal elements of R (might be helpful?)
    plt.figure()
    plt.plot(np.diag(Rmatrix))
    plt.savefig(os.path.join(outdir, 'model_resolution_diagonal.png'))

    # Viewing the total picture of R: shows the model resolution along the diagonal.
    plt.figure(figsize=(12, 8), dpi=300)
    plt.imshow(Rmatrix, aspect=1)
    plt.colorbar()
    plt.savefig(os.path.join(outdir, "Rmatrix.png"))
    return np.diag(Rmatrix), sig_slipb
//  [python]
def edmd(X, Y, psi, evs=5, operator='K'):
    '''
    Conventional EDMD for the Koopman or Perron-Frobenius operator. The matrices X and Y
    contain the input data.

    :param psi:      set of basis functions, see d3s.observables
    :param evs:      number of eigenvalues/eigenvectors
    :param operator: 'K' for Koopman or 'P' for Perron-Frobenius
    :return:         eigenvalues d and corresponding eigenvectors V containing the coefficients for the eigenfunctions
    '''
    PsiX = psi(X)
    PsiY = psi(Y)
    C_0 = PsiX @ PsiX.T
    C_1 = PsiX @ PsiY.T
    if operator == 'P': C_1 = C_1.T

    A = s.pinv(C_0) @ C_1
    d, V = sortEig(A, evs)
    return (A, d, V)
//  [python]
def edmd(X, Y, psi, evs=5, operator='K'):
    '''
    Conventional EDMD for the Koopman or Perron-Frobenius operator. The matrices X and Y
    contain the input data.

    :param psi:      set of basis functions, see d3s.observables
    :param evs:      number of eigenvalues/eigenvectors
    :param operator: 'K' for Koopman or 'P' for Perron-Frobenius
    :return:         eigenvalues d and corresponding eigenvectors V containing the coefficients for the eigenfunctions
    '''
    PsiX = psi(X)
    PsiY = psi(Y)
    C_0 = PsiX @ PsiX.T
    C_1 = PsiX @ PsiY.T
    if operator == 'P': C_1 = C_1.T

    A = _sp.linalg.pinv(C_0) @ C_1
    d, V = sortEig(A, evs)
    return (A, d, V)
//  [python]
def test_hessian_1():
    n = 3
    seqs = [
        [1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2,
         1, 1, 1, 1, 2, 3, 3, 3, 3]]

    model = ContinuousTimeMSM().fit(seqs)
    theta = model.theta_
    C = model.countsmat_

    hessian1 = _ratematrix.hessian(theta, C)
    Hfun = nd.Jacobian(lambda x: _ratematrix.loglikelihood(x, C)[1])
    hessian2 = Hfun(theta)

    # not sure what the cutoff here should be (see plot_test_hessian)
    diff = np.linalg.norm(hessian1 - hessian2)
    print("hessian difference: %f" % diff)
    assert diff < 1e-4

    print(_ratematrix.sigma_pi(-scipy.linalg.pinv(hessian1), theta, n))
//  [python]
def UniformGamma(num_candidates, ranking_size, allow_repetitions):
    validDocs=ranking_size
    if not allow_repetitions:
        validDocs=min(ranking_size, num_candidates)
                
    gamma=numpy.empty((num_candidates*validDocs, num_candidates*validDocs), dtype=numpy.float64)
    if num_candidates==1:
        gamma.fill(1.0)
    else:
        #First set all the off-diagonal blocks
        if allow_repetitions:
            gamma.fill(1.0/(num_candidates*num_candidates))
        else:
            gamma.fill(1.0/(num_candidates*(num_candidates-1)))
            #Correct the diagonal of each off-diagonal block: Pairwise=0
            for p in range(1,validDocs):
                diag=numpy.diagonal(gamma, offset=p*num_candidates)
                diag.setflags(write=True)
                diag.fill(0)
                        
                diag=numpy.diagonal(gamma, offset=-p*num_candidates)
                diag.setflags(write=True)
                diag.fill(0)
                        
        #Now correct the diagonal blocks: Diagonal matrix with marginals = 1/m
        for j in range(validDocs):
            currentStart=j*num_candidates
            currentEnd=(j+1)*num_candidates
            gamma[currentStart:currentEnd, currentStart:currentEnd]=0
            numpy.fill_diagonal(gamma, 1.0/num_candidates)

    gammaInv=numpy.linalg.pinv(gamma)
    return (num_candidates, gammaInv)
//  [python]
def UniformGamma(num_candidates, ranking_size, allow_repetitions):
    validDocs=ranking_size
    if not allow_repetitions:
        validDocs=min(ranking_size, num_candidates)
                
    gamma=numpy.empty((num_candidates*validDocs, num_candidates*validDocs), dtype=numpy.float64)
    if num_candidates==1:
        gamma.fill(1.0)
    else:
        #First set all the off-diagonal blocks
        if allow_repetitions:
            gamma.fill(1.0/(num_candidates*num_candidates))
        else:
            gamma.fill(1.0/(num_candidates*(num_candidates-1)))
            #Correct the diagonal of each off-diagonal block: Pairwise=0
            for p in range(1,validDocs):
                diag=numpy.diagonal(gamma, offset=p*num_candidates)
                diag.setflags(write=True)
                diag.fill(0)
                        
                diag=numpy.diagonal(gamma, offset=-p*num_candidates)
                diag.setflags(write=True)
                diag.fill(0)
                        
        #Now correct the diagonal blocks: Diagonal matrix with marginals = 1/m
        for j in range(validDocs):
            currentStart=j*num_candidates
            currentEnd=(j+1)*num_candidates
            gamma[currentStart:currentEnd, currentStart:currentEnd]=0
            numpy.fill_diagonal(gamma, 1.0/num_candidates)

    gammaInv=scipy.linalg.pinv(gamma)
    return (num_candidates, gammaInv)
//  [python]
def write_wfn_mol(scf_data, ortho_ao, filename, wfn=None,
                  init=None, verbose=False):
    """Generate QMCPACK trial wavefunction.

    Parameters
    ----------
    scf_data : dict
        Dictionary containing scf data extracted from pyscf checkpoint file.
    ortho_ao : bool
        Whether we are working in orthogonalised AO basis or not.
    filename : string
        HDF5 file path to store wavefunction to.
    wfn : tuple
        User defined wavefunction. Not fully supported. Default None.

    Returns
    -------
    wfn : :class:`numpy.ndarray`
        Wavefunction as numpy array. Format depends on wavefunction.
    """
    ghf = False
    mol = scf_data['mol']
    nelec = mol.nelec
    nalpha, nbeta = nelec
    C = scf_data['mo_coeff']
    X = scf_data['X']
    rohf = scf_data.get('rohf', False)
    uhf = scf_data['isUHF']
    # For RHF only nalpha entries will be filled.
    if uhf:
        norb = C[0].shape[-1]
    else:
        norb = C.shape[-1]
    if wfn is None:
        wfn = numpy.zeros((1,norb,nalpha+nbeta), dtype=numpy.complex128)
        wfn_type = 'NOMSD'
        coeffs = numpy.array([1.0+0j])
        if ortho_ao:
            if X.shape[0] != X.shape[1]:
                Xinv = numpy.linalg.pinv(X)
            else:
                Xinv = numpy.linalg.inv(X)
            if uhf:
                # We are assuming C matrix is energy ordered.
                wfn[0,:,:nalpha] = numpy.dot(Xinv, C[0])[:,:nalpha]
                wfn[0,:,nalpha:] = numpy.dot(Xinv, C[1])[:,:nbeta]
            elif rohf:
                wfn[0,:,:nalpha] = numpy.dot(Xinv, C)[:,:nalpha]
                wfn[0,:,nalpha:] = numpy.dot(Xinv, C)[:,:nbeta]
            else:
                wfn[0,:,:nalpha] = numpy.dot(Xinv, C)[:,:nalpha]
        else:
            # Assuming we are working in MO basis, only works for RHF, ROHF trials.
            I = numpy.identity(C.shape[-1], dtype=numpy.float64)
            wfn[0,:,:nalpha] = I[:,:nalpha]
            if rohf:
                wfn[0,:,nalpha:] = I[:,:nbeta]
            if uhf:
                print(" # Warning: UHF trial wavefunction can only be used of "
                      "working in ortho AO basis.")
    write_qmcpack_wfn(filename, (numpy.array([1.0+0j]),wfn), uhf or rohf,
                      nelec, norb, verbose=verbose)
    return nelec
//  [python]
def write_wfn_mol(scf_data, ortho_ao, filename, wfn=None,
                  init=None, verbose=False):
    """Generate QMCPACK trial wavefunction.

    Parameters
    ----------
    scf_data : dict
        Dictionary containing scf data extracted from pyscf checkpoint file.
    ortho_ao : bool
        Whether we are working in orthogonalised AO basis or not.
    filename : string
        HDF5 file path to store wavefunction to.
    wfn : tuple
        User defined wavefunction. Not fully supported. Default None.

    Returns
    -------
    wfn : :class:`numpy.ndarray`
        Wavefunction as numpy array. Format depends on wavefunction.
    """
    ghf = False
    mol = scf_data['mol']
    nelec = mol.nelec
    nalpha, nbeta = nelec
    C = scf_data['mo_coeff']
    X = scf_data['X']
    rohf = scf_data.get('rohf', False)
    uhf = scf_data['isUHF']
    # For RHF only nalpha entries will be filled.
    if uhf:
        norb = C[0].shape[-1]
    else:
        norb = C.shape[-1]
    if wfn is None:
        wfn = numpy.zeros((1,norb,nalpha+nbeta), dtype=numpy.complex128)
        wfn_type = 'NOMSD'
        coeffs = numpy.array([1.0+0j])
        if ortho_ao:
            if X.shape[0] != X.shape[1]:
                Xinv = scipy.linalg.pinv(X)
            else:
                Xinv = scipy.linalg.inv(X)
            if uhf:
                # We are assuming C matrix is energy ordered.
                wfn[0,:,:nalpha] = numpy.dot(Xinv, C[0])[:,:nalpha]
                wfn[0,:,nalpha:] = numpy.dot(Xinv, C[1])[:,:nbeta]
            elif rohf:
                wfn[0,:,:nalpha] = numpy.dot(Xinv, C)[:,:nalpha]
                wfn[0,:,nalpha:] = numpy.dot(Xinv, C)[:,:nbeta]
            else:
                wfn[0,:,:nalpha] = numpy.dot(Xinv, C)[:,:nalpha]
        else:
            # Assuming we are working in MO basis, only works for RHF, ROHF trials.
            I = numpy.identity(C.shape[-1], dtype=numpy.float64)
            wfn[0,:,:nalpha] = I[:,:nalpha]
            if rohf:
                wfn[0,:,nalpha:] = I[:,:nbeta]
            if uhf:
                print(" # Warning: UHF trial wavefunction can only be used of "
                      "working in ortho AO basis.")
    write_qmcpack_wfn(filename, (numpy.array([1.0+0j]),wfn), uhf or rohf,
                      nelec, norb, verbose=verbose)
    return nelec
//  [python]
def regressOut(Y, X):
    """
    regresses out X from Y
    """
    Xd = s.pinv(X)
    Y_out = Y-X.dot(Xd.dot(Y))
    return Y_out
//  [python]
def regressOut(Y, X):
    """
    regresses out X from Y
    """
    Xd = la.pinv(X)
    Y_out = Y-X.dot(Xd.dot(Y))
    return Y_out
//  [python]
def kedmd(X, Y, k, epsilon=0, evs=5, operator='P'):
    '''
    Kernel EDMD for the Koopman or Perron-Frobenius operator. The matrices X and Y
    contain the input data.

    :param k:        kernel, see d3s.kernels
    :param epsilon:  regularization parameter
    :param evs:      number of eigenvalues/eigenvectors
    :param operator: 'K' for Koopman or 'P' for Perron-Frobenius (note that the default is P here)
    :return:         eigenvalues d and eigenfunctions evaluated in X
    '''
    if isinstance(X, list): # e.g., for strings
        n = len(X)
    else:
        n = X.shape[1]

    G_0 = _kernels.gramian(X, k)
    G_1 = _kernels.gramian2(X, Y, k)
    if operator == 'K': G_1 = G_1.T

    A = _np.linalg.pinv(G_0 + epsilon*_np.eye(n), rcond=1e-15) @ G_1
    d, V = sortEig(A, evs)
    if operator == 'K': V = G_0 @ V
    return (d, V)
//  [python]
def kedmd(X, Y, k, epsilon=0, evs=5, operator='P'):
    '''
    Kernel EDMD for the Koopman or Perron-Frobenius operator. The matrices X and Y
    contain the input data.

    :param k:        kernel, see d3s.kernels
    :param epsilon:  regularization parameter
    :param evs:      number of eigenvalues/eigenvectors
    :param operator: 'K' for Koopman or 'P' for Perron-Frobenius (note that the default is P here)
    :return:         eigenvalues d and eigenfunctions evaluated in X
    '''
    if isinstance(X, list): # e.g., for strings
        n = len(X)
    else:
        n = X.shape[1]

    G_0 = _kernels.gramian(X, k)
    G_1 = _kernels.gramian2(X, Y, k)
    if operator == 'K': G_1 = G_1.T

    A = _sp.linalg.pinv(G_0 + epsilon*_np.eye(n), rcond=1e-15) @ G_1
    d, V = sortEig(A, evs)
    if operator == 'K': V = G_0 @ V
    return (d, V)
//  [python]
def gedmd(X, Y, Z, psi, evs=5, operator='K'):
    '''
    Generator EDMD for the Koopman operator. The matrices X and Y
    contain the input data. For stochastic systems, Z contains the
    diffusion term evaluated in all data points X. If the system is
    deterministic, set Z = None.
    '''
    PsiX = psi(X)
    dPsiY = _np.einsum('ijk,jk->ik', psi.diff(X), Y)
    if not (Z is None): # stochastic dynamical system
        n = PsiX.shape[0] # number of basis functions
        ddPsiX = psi.ddiff(X) # second-order derivatives
        S = _np.einsum('ijk,ljk->ilk', Z, Z) # sigma \cdot sigma^T
        for i in range(n):
            dPsiY[i, :] += 0.5*_np.sum( ddPsiX[i, :, :, :] * S, axis=(0,1) )
    
    C_0 = PsiX @ PsiX.T
    C_1 = PsiX @ dPsiY.T
    if operator == 'P': C_1 = C_1.T

    A = _sp.linalg.pinv2(C_0) @ C_1
    
    d, V = sortEig(A, evs, which='SM')
    
    return (A, d, V)
//  [python]
def gedmd(X, Y, Z, psi, evs=5, operator='K'):
    '''
    Generator EDMD for the Koopman operator. The matrices X and Y
    contain the input data. For stochastic systems, Z contains the
    diffusion term evaluated in all data points X. If the system is
    deterministic, set Z = None.
    '''
    PsiX = psi(X)
    dPsiY = _np.einsum('ijk,jk->ik', psi.diff(X), Y)
    if not (Z is None): # stochastic dynamical system
        n = PsiX.shape[0] # number of basis functions
        ddPsiX = psi.ddiff(X) # second-order derivatives
        S = _np.einsum('ijk,ljk->ilk', Z, Z) # sigma \cdot sigma^T
        for i in range(n):
            dPsiY[i, :] += 0.5*_np.sum( ddPsiX[i, :, :, :] * S, axis=(0,1) )
    
    C_0 = PsiX @ PsiX.T
    C_1 = PsiX @ dPsiY.T
    if operator == 'P': C_1 = C_1.T

    A = _sp.linalg.pinv(C_0) @ C_1
    
    d, V = sortEig(A, evs, which='SM')
    
    return (A, d, V)