scipy.sparse.linalg.

LaplacianNd#

class scipy.sparse.linalg.LaplacianNd(*args, **kwargs)[Quelle]#

Der Gitter-Laplace-Operator in N Dimensionen und seine Eigenwerte/Eigenvektoren.

Konstruiert den Laplace-Operator auf einem gleichmäßigen rechteckigen Gitter in N Dimensionen und gibt seine Eigenwerte und Eigenvektoren aus. Die Laplace-Matrix L ist eine quadratische, negativ definite, reell symmetrische Matrix mit vorzeichenbehafteten ganzzahligen Einträgen und ansonsten Nullen.

Parameter:
grid_shapetuple

Ein Tupel von ganzen Zahlen der Länge N (entsprechend der Dimension des Laplace-Operators), wobei jeder Eintrag die Größe dieser Dimension angibt. Die Laplace-Matrix ist quadratisch mit der Größe np.prod(grid_shape).

boundary_conditions{‘neumann’, ‘dirichlet’, ‘periodic’}, optional

Der Typ der Randbedingungen an den Rändern des Gitters. Gültige Werte sind 'dirichlet' oder 'neumann'``(Standard) oder ``'periodic'.

dtypedtype

Numerischer Typ des Arrays. Standard ist np.int8.

Attribute:
H

Hermitesche Adjungierte.

T

Transponiert diesen linearen Operator.

Methoden

toarray()

Konstruiert ein dichtes Array aus Laplace-Daten

tosparse()

Konstruiert ein spärliches Array aus Laplace-Daten

eigenvalues(m=None)

Konstruiert ein 1D-Array der m größten (kleinsten im Betrag) Eigenwerte der Laplace-Matrix in aufsteigender Reihenfolge.

eigenvectors(m=None)

Konstruiert das Array mit Spalten, die aus den m Eigenvektoren (float) des Nd-Laplace-Operators gebildet werden, die den m geordneten Eigenwerten entsprechen.

.. versionadded:: 1.12.0

Hinweise

Im Vergleich zur MATLAB/Octave-Implementierung [1] des 1-, 2- und 3-D-Laplace-Operators erlaubt dieser Code den beliebigen N-D-Fall und die matrixfreie Callable-Option, ist aber derzeit auf reine Dirichlet-, Neumann- oder Periodische Randbedingungen beschränkt.

Die Laplace-Matrix eines Graphen (scipy.sparse.csgraph.laplacian) eines rechteckigen Gitters entspricht dem negativen Laplace-Operator mit Neumann-Bedingungen, d.h. boundary_conditions = 'neumann'.

Alle Eigenwerte und Eigenvektoren des diskreten Laplace-Operators für ein N-dimensionales reguläres Gitter der Form grid_shape mit dem Gitter-Schrittweite h=1 sind analytisch bekannt [2].

Referenzen

[2]

„Eigenwerte und Eigenvektoren der zweiten Ableitung“, Wikipedia https://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors_of_the_second_derivative

Beispiele

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

Der eindimensionale Laplace-Operator, der im Folgenden für reine Neumann-Randbedingungen auf einem regulären Gitter mit n=6 Gitterpunkten demonstriert wird, ist genau der negative Graph-Laplace-Operator für den ungerichteten linearen Graphen mit n Knoten unter Verwendung der spärlichen Adjazenzmatrix G, die durch die berühmte tridiagonale Matrix dargestellt wird.

>>> n = 6
>>> G = diags_array(np.ones(n - 1), offsets=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

Da alle Matrixeinträge des Laplace-Operators ganze Zahlen sind, ist 'int8' der Standard-Datentyp für die Speicherung von Matrixdarstellungen.

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

Es können beliebig viele extreme Eigenwerte und/oder Eigenvektoren berechnet werden.

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

Der zweidimensionale Laplace-Operator wird auf einem regulären Gitter mit grid_shape = (2, 3) Punkten in jeder Dimension illustriert.

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

Die Nummerierung der Gitterpunkte erfolgt wie folgt:

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

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

Jede der Randbedingungen 'dirichlet', 'periodic' und 'neumann' wird separat illustriert; mit '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

mit '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

und mit '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]], 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([-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