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, type=1)#

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).

  • type (int) –

    For the generalized eigenproblem, this value specifies the type of problem. Only 1, 2, and 3 are supported.

    • When type=1, solve \(\boldsymbol{Az}=\lambda\boldsymbol{Bz}\).

    • When type=2, solve \(\boldsymbol{ABz}=\lambda\boldsymbol{z}\).

    • When type=3, solve \(\boldsymbol{BAz}=\lambda\boldsymbol{z}\).

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, type=1)#

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).

  • type (int) –

    For the generalized eigenproblem, this value specifies the type of problem. Only 1, 2, and 3 are supported.

    • When type=1, solve \(\boldsymbol{Az}=\lambda\boldsymbol{Bz}\).

    • When type=2, solve \(\boldsymbol{ABz}=\lambda\boldsymbol{z}\).

    • When type=3, solve \(\boldsymbol{BAz}=\lambda\boldsymbol{z}\).

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
ssspy.linalg.gmeanmh(A, B, type=1)#

Compute the geometric mean of complex Hermitian (conjugate symmetric) or real symmetric matrices.

The geometric mean of \(\boldsymbol{A}\) and \(\boldsymbol{B}\) is defined as follows [1]:

\[\begin{split}\boldsymbol{A}\#\boldsymbol{B} &= \boldsymbol{A}^{1/2} (\boldsymbol{A}^{-1/2}\boldsymbol{B}\boldsymbol{A}^{-1/2})^{1/2} \boldsymbol{A}^{1/2} \\ &= \boldsymbol{A}(\boldsymbol{A}^{-1}\boldsymbol{B})^{1/2} \\ &= (\boldsymbol{A}\boldsymbol{B}^{-1})^{1/2}\boldsymbol{B}.\end{split}\]

This is a solution of the following equation for complex Hermitian or real symmetric matrices, \(\boldsymbol{A}\), \(\boldsymbol{B}\), and \(\boldsymbol{X}\):

\[\boldsymbol{X}\boldsymbol{A}^{-1}\boldsymbol{X} = \boldsymbol{B}.\]

Note

In this toolkit, \(\boldsymbol{A}\#\boldsymbol{B}\) is computed by \(\boldsymbol{B}(\boldsymbol{B}^{-1}\boldsymbol{A})^{1/2}\) in terms of computational speed. Note that \(\boldsymbol{A}\#\boldsymbol{B}\) is equal to \(\boldsymbol{B}\#\boldsymbol{A}\). For comparison of computational time, see https://github.com/tky823/ssspy/issues/210.

Note

\((\boldsymbol{B}^{-1}\boldsymbol{A})^{1/2}\) is computed by generalized eigendecomposition. Let \(\lambda\) and \(z\) be the eigenvalue and eigenvector of the generalized eigenproblem \(\boldsymbol{Az}=\lambda\boldsymbol{Bz}\). Then, \((\boldsymbol{B}^{-1}\boldsymbol{A})^{1/2}\) is computed by \(\boldsymbol{Z}\boldsymbol{\Lambda}^{1/2}\boldsymbol{Z}^{-1}\), where the main diagonals of \(\boldsymbol{\Lambda}\) are \(\lambda\) s and the columns of \(\boldsymbol{Z}\) are \(\boldsymbol{z}\) s.

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

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

  • type (int) –

    This value specifies the type of geometric mean. Only 1, 2, and 3 are supported.

    • When type=1, return \(\boldsymbol{A}\#\boldsymbol{B}\).

    • When type=2, return \(\boldsymbol{A}^{-1}\#\boldsymbol{B}\).

    • When type=3, return \(\boldsymbol{A}\#\boldsymbol{B}^{-1}\).

Return type:

ndarray

Returns:

Geometric mean of matrices with shape of (*, n_channels, n_channels).

ssspy.linalg.lqpqm2(H, v, z, flooring_fn=functools.partial(<function max_flooring>, eps=1e-10), singular_fn='flooring', max_iter=10)#

Solve of log-quadratically penelized quadratic minimization (type 2).

\[\check{\boldsymbol{q}}_{in} = \min_{\check{\boldsymbol{q}}_{in}} ~~\check{\boldsymbol{q}}_{in}^{\mathsf{H}}\check{\boldsymbol{q}}_{in} - \log\left((\check{\boldsymbol{q}}_{in}+\boldsymbol{v}_{in})^{\mathsf{H}} \boldsymbol{H}_{in}(\check{\boldsymbol{q}}_{in}+\boldsymbol{v}_{in}) + z_{in} \right)\]
Parameters:
  • H (numpy.ndarray) – Positive semidefinite matrices of shape (n_bins, n_sources - 1, n_sources - 1).

  • v (numpy.ndarray) – Linear terms in LQPQM of shape (n_bins, n_sources - 1).

  • z (numpy.ndarray) – Constant terms in LQPQM of shape (n_bins,).

  • flooring_fn (callable, optional) – A flooring function for numerical stability. This function is expected to return the same shape tensor as the input. If you explicitly set flooring_fn=None, the identity function (lambda x: x) is used. Default: functools.partial(max_flooring, eps=1e-10).

  • singular_fn (callable, optional) – A flooring function to return singular condition. This function is expected to return the same shape bool tensor as the input. If singular_fn=None, lambda x: x == 0 is used. Default: flooring.

  • max_iter (int) – Maximum number of Newton-Raphson method. Default: 10.

Returns:

Solutions of LQPQM type-2 of shape (n_bins, n_sources - 1).

Return type:

np.ndarray