36

特定の行列のヌル空間 (Ax=0 の解空間) を見つけようとしています。2 つの例を見つけましたが、どちらも動作しないようです。さらに、そこに到達するために彼らが何をしているのか理解できないため、デバッグできません。誰かが私にこれを説明してくれることを願っています。

ドキュメント ページ ( numpy.linalg.svd、およびnumpy.compress) はわかりにくいです。C = [A|0]これを行うには、行列を作成し、縮小された行階層形式を見つけ、行ごとに変数を解決することで学習しました。これらの例では、それがどのように行われているかを理解できないようです。

助けてくれてありがとう!

ウィキペディアの例と同じである私のサンプルマトリックスは次のとおりです。

A = matrix([
    [2,3,5],
    [-4,2,3]
    ])  

メソッド(ここにあります、およびここにあります):

import scipy
from scipy import linalg, matrix
def null(A, eps=1e-15):
    u, s, vh = scipy.linalg.svd(A)
    null_mask = (s <= eps)
    null_space = scipy.compress(null_mask, vh, axis=0)
    return scipy.transpose(null_space)

試してみると、空の行列が返されます。

Python 2.6.6 (r266:84292, Sep 15 2010, 16:22:56) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import scipy
>>> from scipy import linalg, matrix
>>> def null(A, eps=1e-15):
...    u, s, vh = scipy.linalg.svd(A)
...    null_mask = (s <= eps)
...    null_space = scipy.compress(null_mask, vh, axis=0)
...    return scipy.transpose(null_space)
... 
>>> A = matrix([
...     [2,3,5],
...     [-4,2,3]
...     ])  
>>> 
>>> null(A)
array([], shape=(3, 0), dtype=float64)
>>> 
4

6 に答える 6

24

Sympy はこれを簡単にします。

>>> from sympy import Matrix
>>> A = [[2, 3, 5], [-4, 2, 3], [0, 0, 0]]
>>> A = Matrix(A)
>>> A * A.nullspace()[0]
Matrix([
[0],
[0],
[0]])
>>> A.nullspace()
[Matrix([
[-1/16],
[-13/8],
[    1]])]
于 2014-11-10T02:09:03.040 に答える
11

行列の SVD 分解を取得しますAs固有値のベクトルです。論理値のベクトルによって与えられる、ほぼゼロの固有値 ($A*x=\lambda*x$ where $\abs(\lambda)<\epsilon$ を参照) に関心がありますnull_mask

次に、ほとんどゼロの固有値に対応する固有ベクトルをリストから抽出しますvh。これは、まさに探しているものです: null 空間にまたがる方法です。基本的に、行を抽出してから結果を転置して、固有ベクトルを列とする行列を取得します。

于 2011-05-04T20:05:52.020 に答える
7

それは私にとってはうまくいっているようです:

A = matrix([[2,3,5],[-4,2,3],[0,0,0]])
A * null(A)
>>> [[  4.02455846e-16]
>>>  [  1.94289029e-16]
>>>  [  0.00000000e+00]]
于 2011-05-04T20:29:13.337 に答える
3

より高速ですが、数値的に安定していない方法は、次のようなランクを明らかにする QR 分解を使用することscipy.linalg.qrですpivoting=True

import numpy as np
from scipy.linalg import qr

def qr_null(A, tol=None):
    Q, R, P = qr(A.T, mode='full', pivoting=True)
    tol = np.finfo(R.dtype).eps if tol is None else tol
    rnk = min(A.shape) - np.abs(np.diag(R))[::-1].searchsorted(tol)
    return Q[:, rnk:].conj()

例えば:

A = np.array([[ 2, 3, 5],
              [-4, 2, 3],
              [ 0, 0, 0]])
Z = qr_null(A)

print(A.dot(Z))
#[[  4.44089210e-16]
# [  6.66133815e-16]
# [  0.00000000e+00]]
于 2015-11-09T22:15:18.227 に答える
2

あなたの方法はほぼ正しいです。問題は、関数 scipy.linalg.svd によって返される s の形状が (K,) (K=min(M,N)) であることです。したがって、あなたの例では、s には 2 つのエントリ (最初の 2 つの特異ベクトルの特異値) しかありません。null 関数を次のように修正すると、任意のサイズの行列に対して機能するようになります。

import scipy
import numpy as np
from scipy import linalg, matrix
def null(A, eps=1e-12):
...    u, s, vh = scipy.linalg.svd(A)
...    padding = max(0,np.shape(A)[1]-np.shape(s)[0])
...    null_mask = np.concatenate(((s <= eps), np.ones((padding,),dtype=bool)),axis=0)
...    null_space = scipy.compress(null_mask, vh, axis=0)
...    return scipy.transpose(null_space)
A = matrix([[2,3,5],[-4,2,3]])
print A*null(A)
>>>[[  4.44089210e-16]
>>> [  6.66133815e-16]]
A = matrix([[1,0,1,0],[0,1,0,0],[0,0,0,0],[0,0,0,0]])
print null(A)
>>>[[ 0.         -0.70710678]
>>> [ 0.          0.        ]
>>> [ 0.          0.70710678]
>>> [ 1.          0.        ]]
print A*null(A)
>>>[[ 0.  0.]
>>> [ 0.  0.]
>>> [ 0.  0.]
>>> [ 0.  0.]]
于 2014-10-23T19:25:41.213 に答える