scipy.sparse.linalg.

LaplacianNd#

class scipy.sparse.linalg.LaplacianNd(*args, **kwargs)[源代码][源代码]#

N 维网格拉普拉斯算子和其特征值/特征向量。

N 维的均匀矩形网格上构造拉普拉斯算子,并输出其特征值和特征向量。拉普拉斯算子 L 是一个方阵,负定,实对称数组,带有符号整数项,其他地方为零。

参数:
grid_shape元组

一个长度为 N 的整数元组(对应于拉普拉斯算子的维度),其中每个条目给出该维度的大小。拉普拉斯矩阵的大小为 np.prod(grid_shape) 的平方。

边界条件{‘neumann’, ‘dirichlet’, ‘periodic’}, 可选

网格边界上的边界条件的类型。有效值为 'dirichlet''neumann'``(默认)或 ``'periodic'

dtypedtype

数组的数值类型。默认是 np.int8

属性:
H

Hermitian 伴随。

T

转置这个线性算子。

方法

toarray()

从拉普拉斯数据构建密集数组

tosparse()

从拉普拉斯数据构建稀疏数组

特征值(m=None)

构造一个一维数组,包含拉普拉斯矩阵的 m 个最大(绝对值最小)的特征值,按升序排列。

特征向量(m=None):

构建一个数组,其列由 m 个对应于 m 个有序特征值的 Nd 拉普拉斯矩阵的特征向量(float)组成。

.. versionadded:: 1.12.0

注释

与 MATLAB/Octave 实现的 1-、2- 和 3-D 拉普拉斯算子 [1] 相比,此代码允许任意 N-D 情况和无矩阵的可调用选项,但目前仅限于纯 Dirichlet、Neumann 或周期性边界条件。

图的拉普拉斯矩阵(scipy.sparse.csgraph.laplacian)对于矩形网格对应于带有诺伊曼边界条件的负拉普拉斯算子,即 boundary_conditions = 'neumann'

对于一个形状为 grid_shapeN 维规则网格,离散拉普拉斯算子的所有特征值和特征向量在网格步长 h=1 的情况下是解析已知的 [2]。

参考文献

[2]

“二阶导数的特征值和特征向量”,维基百科 https://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors_of_the_second_derivative

示例

>>> import numpy as np
>>> from scipy.sparse.linalg import LaplacianNd
>>> from scipy.sparse import diags, csgraph
>>> from scipy.linalg import eigvalsh

下面展示的一维拉普拉斯算子在规则网格上使用 n=6 个网格点且纯诺伊曼边界条件的情况下,正是无向线性图的负图拉普拉斯算子,该图具有 n 个顶点,使用由著名的三对角矩阵表示的稀疏邻接矩阵 G

>>> n = 6
>>> G = diags(np.ones(n - 1), 1, format='csr')
>>> Lf = csgraph.laplacian(G, symmetrized=True, form='function')
>>> grid_shape = (n, )
>>> lap = LaplacianNd(grid_shape, boundary_conditions='neumann')
>>> np.array_equal(lap.matmat(np.eye(n)), -Lf(np.eye(n)))
True

由于拉普拉斯矩阵的所有条目都是整数,'int8' 是存储矩阵表示的默认数据类型。

>>> lap.tosparse()
<DIAgonal sparse array of dtype 'int8'
    with 16 stored elements (3 diagonals) and shape (6, 6)>
>>> lap.toarray()
array([[-1,  1,  0,  0,  0,  0],
       [ 1, -2,  1,  0,  0,  0],
       [ 0,  1, -2,  1,  0,  0],
       [ 0,  0,  1, -2,  1,  0],
       [ 0,  0,  0,  1, -2,  1],
       [ 0,  0,  0,  0,  1, -1]], dtype=int8)
>>> np.array_equal(lap.matmat(np.eye(n)), lap.toarray())
True
>>> np.array_equal(lap.tosparse().toarray(), lap.toarray())
True

可以计算任意数量的极值特征值和/或特征向量。

>>> lap = LaplacianNd(grid_shape, boundary_conditions='periodic')
>>> lap.eigenvalues()
array([-4., -3., -3., -1., -1.,  0.])
>>> lap.eigenvalues()[-2:]
array([-1.,  0.])
>>> lap.eigenvalues(2)
array([-1.,  0.])
>>> lap.eigenvectors(1)
array([[0.40824829],
       [0.40824829],
       [0.40824829],
       [0.40824829],
       [0.40824829],
       [0.40824829]])
>>> lap.eigenvectors(2)
array([[ 0.5       ,  0.40824829],
       [ 0.        ,  0.40824829],
       [-0.5       ,  0.40824829],
       [-0.5       ,  0.40824829],
       [ 0.        ,  0.40824829],
       [ 0.5       ,  0.40824829]])
>>> lap.eigenvectors()
array([[ 0.40824829,  0.28867513,  0.28867513,  0.5       ,  0.5       ,
         0.40824829],
       [-0.40824829, -0.57735027, -0.57735027,  0.        ,  0.        ,
         0.40824829],
       [ 0.40824829,  0.28867513,  0.28867513, -0.5       , -0.5       ,
         0.40824829],
       [-0.40824829,  0.28867513,  0.28867513, -0.5       , -0.5       ,
         0.40824829],
       [ 0.40824829, -0.57735027, -0.57735027,  0.        ,  0.        ,
         0.40824829],
       [-0.40824829,  0.28867513,  0.28867513,  0.5       ,  0.5       ,
         0.40824829]])

二维拉普拉斯算子在一个规则网格上进行了说明,该网格在每个维度上有 grid_shape = (2, 3) 个点。

>>> grid_shape = (2, 3)
>>> n = np.prod(grid_shape)

网格点的编号如下:

>>> np.arange(n).reshape(grid_shape + (-1,))
array([[[0],
        [1],
        [2]],

       [[3],
        [4],
        [5]]])

每个边界条件 'dirichlet''periodic''neumann' 都分别进行了说明;其中 'dirichlet'

>>> lap = LaplacianNd(grid_shape, boundary_conditions='dirichlet')
>>> lap.tosparse()
<Compressed Sparse Row sparse array of dtype 'int8'
    with 20 stored elements and shape (6, 6)>
>>> lap.toarray()
array([[-4,  1,  0,  1,  0,  0],
       [ 1, -4,  1,  0,  1,  0],
       [ 0,  1, -4,  0,  0,  1],
       [ 1,  0,  0, -4,  1,  0],
       [ 0,  1,  0,  1, -4,  1],
       [ 0,  0,  1,  0,  1, -4]], dtype=int8)
>>> np.array_equal(lap.matmat(np.eye(n)), lap.toarray())
True
>>> np.array_equal(lap.tosparse().toarray(), lap.toarray())
True
>>> lap.eigenvalues()
array([-6.41421356, -5.        , -4.41421356, -3.58578644, -3.        ,
       -1.58578644])
>>> eigvals = eigvalsh(lap.toarray().astype(np.float64))
>>> np.allclose(lap.eigenvalues(), eigvals)
True
>>> np.allclose(lap.toarray() @ lap.eigenvectors(),
...             lap.eigenvectors() @ np.diag(lap.eigenvalues()))
True

使用 'periodic'

>>> lap = LaplacianNd(grid_shape, boundary_conditions='periodic')
>>> lap.tosparse()
<Compressed Sparse Row sparse array of dtype 'int8'
    with 24 stored elements and shape (6, 6)>
>>> lap.toarray()
    array([[-4,  1,  1,  2,  0,  0],
           [ 1, -4,  1,  0,  2,  0],
           [ 1,  1, -4,  0,  0,  2],
           [ 2,  0,  0, -4,  1,  1],
           [ 0,  2,  0,  1, -4,  1],
           [ 0,  0,  2,  1,  1, -4]], dtype=int8)
>>> np.array_equal(lap.matmat(np.eye(n)), lap.toarray())
True
>>> np.array_equal(lap.tosparse().toarray(), lap.toarray())
True
>>> lap.eigenvalues()
array([-7., -7., -4., -3., -3.,  0.])
>>> eigvals = eigvalsh(lap.toarray().astype(np.float64))
>>> np.allclose(lap.eigenvalues(), eigvals)
True
>>> np.allclose(lap.toarray() @ lap.eigenvectors(),
...             lap.eigenvectors() @ np.diag(lap.eigenvalues()))
True

并且使用 'neumann'

>>> lap = LaplacianNd(grid_shape, boundary_conditions='neumann')
>>> lap.tosparse()
<Compressed Sparse Row sparse array of dtype 'int8'
    with 20 stored elements and shape (6, 6)>
>>> lap.toarray()
array([[-2,  1,  0,  1,  0,  0],
       [ 1, -3,  1,  0,  1,  0],
       [ 0,  1, -2,  0,  0,  1],
       [ 1,  0,  0, -2,  1,  0],
       [ 0,  1,  0,  1, -3,  1],
       [ 0,  0,  1,  0,  1, -2]])
>>> np.array_equal(lap.matmat(np.eye(n)), lap.toarray())
True
>>> np.array_equal(lap.tosparse().toarray(), lap.toarray())
True
>>> lap.eigenvalues()
array([-5., -3., -3., -2., -1.,  0.])
>>> eigvals = eigvalsh(lap.toarray().astype(np.float64))
>>> np.allclose(lap.eigenvalues(), eigvals)
True
>>> np.allclose(lap.toarray() @ lap.eigenvectors(),
...             lap.eigenvectors() @ np.diag(lap.eigenvalues()))
True