ssspy.linalg#

ssspy.linalg is linear algebra module related to source separation.

Algorithms#

ssspy.linalg.inv2(X)#

Compute the (multiplicative) inverse of a 2x2 matrix.

Parameters:

X (numpy.ndarray) – 2x2 matrix to be inverted. The shape is (*, 2, 2).

Returns:

(Multiplicative) inverse of the matrix X.

Return type:

numpy.ndarray

Examples

>>> import numpy as np
>>> from ssspy.linalg import inv2
>>> X = np.array([[0, 1], [2, 3]])
>>> X_inv = inv2(X)
>>> np.allclose(X @ X_inv, np.eye(2))
True
>>> np.allclose(X_inv @ X, np.eye(2))
True
>>> import numpy as np
>>> from ssspy.linalg import inv2
>>> X = np.array([[[0, 1], [2, 3]], [[4, 5], [6, 7]]])
>>> inv2(X)
array([[[-1.5,  0.5],
        [ 1. , -0. ]],

    [[-3.5,  2.5],
        [ 3. , -2. ]]])
ssspy.linalg.eigh(A, B=None)#

Compute the (generalized) eigenvalues and eigenvectors of a complex Hermitian (conjugate symmetric) or a real symmetric matrix.

If B is None, solve \(\boldsymbol{A}\boldsymbol{z} = \lambda\boldsymbol{z}\).

If B is given, solve \(\boldsymbol{A}\boldsymbol{z} = \lambda\boldsymbol{B}\boldsymbol{z}\).

Parameters:
  • A (numpy.ndarray) – A complex Hermitian matrix with shape of (*, n_channels, n_channels).

  • B (numpy.ndarray, optional) – A complex Hermitian matrix with shape of (*, n_channels, n_channels).

Return type:

Union[ndarray, Tuple[ndarray, ndarray]]

Returns:

A tuple of (eigenvalues, eigenvectors)
  • Eigenvalues have shape of (*, n_channels).

  • Eigenvectors have shape of (*, n_channels, n_channels).

Note

If B is given, we use cholesky decomposition to satisfy \(\boldsymbol{L}\boldsymbol{L}^{\mathsf{H}}=\boldsymbol{B}\).

Then, solve \(\boldsymbol{C}\boldsymbol{y} = \lambda\boldsymbol{y}\), where \(\boldsymbol{C}=\boldsymbol{L}^{-1}\boldsymbol{A}\boldsymbol{L}^{-\mathsf{H}}\).

The generalized eigenvalues of \(\boldsymbol{A}\) and \(\boldsymbol{B}\) are computed by \(\boldsymbol{L}^{-\mathsf{H}}\boldsymbol{y}\).

Examples

>>> import numpy as np
>>> from ssspy.linalg import eigh
>>> A = np.array([[1, -2j], [2j, 3]])
>>> lamb, z = eigh(A)
>>> lamb; z
array([-0.23606798,  4.23606798])
array([[-0.85065081+0.j        , -0.52573111+0.j        ],
    [ 0.        +0.52573111j,  0.        -0.85065081j]])
>>> np.allclose(A @ z, lamb * z)
True
>>> import numpy as np
>>> from ssspy.linalg import eigh
>>> A = np.array([[1, -2j], [2j, 3]])
>>> B = np.array([[2, -3j], [3j, 5]])
>>> lamb, z = eigh(A, B)
>>> lamb; z
array([-1.61803399,  0.61803399])
array([[ 2.22703273+0.j        , -0.20081142+0.j        ],
    [ 0.        -1.37638192j,  0.        -0.3249197j ]])
>>> np.allclose(A @ z, lamb * (B @ z))
True
ssspy.linalg.eigh2(A, B=None)#

Compute the (generalized) eigenvalues and eigenvectors of a 2x2 complex Hermitian (conjugate symmetric) or a real symmetric matrix.

If B is None, solve \(\boldsymbol{A}\boldsymbol{z} = \lambda\boldsymbol{z}\).

If B is given, solve \(\boldsymbol{A}\boldsymbol{z} = \lambda\boldsymbol{B}\boldsymbol{z}\).

Parameters:
  • A (numpy.ndarray) – A complex Hermitian matrix with shape of (*, 2, 2).

  • B (numpy.ndarray, optional) – A complex Hermitian matrix with shape of (*, 2, 2).

Return type:

Union[ndarray, Tuple[ndarray, ndarray]]

Returns:

A tuple of (eigenvalues, eigenvectors)
  • Eigenvalues have shape of (*, 2).

  • Eigenvectors have shape of (*, 2, 2).

Note

If B is given, we use cholesky decomposition to satisfy \(\boldsymbol{L}\boldsymbol{L}^{\mathsf{H}}=\boldsymbol{B}\).

Then, solve \(\boldsymbol{C}\boldsymbol{y} = \lambda\boldsymbol{y}\), where \(\boldsymbol{C}=\boldsymbol{L}^{-1}\boldsymbol{A}\boldsymbol{L}^{-\mathsf{H}}\).

The generalized eigenvalues of \(\boldsymbol{A}\) and \(\boldsymbol{B}\) are computed by \(\boldsymbol{L}^{-\mathsf{H}}\boldsymbol{y}\).

See also https://github.com/tky823/ssspy/issues/115 for this implementation.

Examples

>>> import numpy as np
>>> from ssspy.linalg import eigh2
>>> A = np.array([[1, -2j], [2j, 3]])
>>> lamb, z = eigh2(A)
>>> lamb; z
array([-0.23606798,  4.23606798])
array([[-0.85065081+0.j        , -0.52573111+0.j        ],
    [ 0.        +0.52573111j,  0.        -0.85065081j]])
>>> np.allclose(A @ z, lamb * z)
True
>>> import numpy as np
>>> from ssspy.linalg import eigh2
>>> A = np.array([[1, -2j], [2j, 3]])
>>> B = np.array([[2, -3j], [3j, 5]])
>>> lamb, z = eigh2(A, B)
>>> lamb; z
array([-1.61803399,  0.61803399])
array([[ 2.22703273+0.j        , -0.20081142+0.j        ],
    [ 0.        -1.37638192j,  0.        -0.3249197j ]])
>>> np.allclose(A @ z, lamb * (B @ z))
True