簡體   English   中英

使用 Eigen 庫,我可以獲得只有一個“近似”矩陣的 kernel 嗎?

[英]Using the Eigen library, can I get the kernel of a matrix which only has one "approximately"?

我需要找到一個 3*3 矩陣的 kernel(又名 null 空間),它的滿秩為 3,但非常接近單數,因此是秩 2。這意味着它沒有 null 空間,除非你用一些東西尋找它“寬容”。

在 Scilab(它是 Matlab 的免費且功能較少的替代品)中,我可以執行以下操作:

--> Rx_1  = 

  -0.000004    0.0000376  -0.0000261
  -0.0000017  -0.459682    0.84146  
   0.0000458  -0.841457   -0.459684 


--> kernel(Rx_1)  ans  =

    []         <--- no exact null space


--> kernel(Rx_1, 0.0001)  ans  =    <--- this 0.0001 is my tolerance

   1.
   0.0000411        <--- null space basis found with "tolerance".
   0.0000244

但是,當我go到C++時,我不知道如何在Eigen中引入容差:

FullPivLU<MatrixXd> lu(Rx_1);        <--- lu won't take any extra arguments
MatrixXd A_null_space = lu.kernel();

我能做什么?

我對Eigen庫不是很熟悉。 但我知道它可用於執行許多分解,還可以用於查找特征空間(考慮到名稱,如果沒有,那將是令人驚訝的)。 例如使用EigenSolver ,或者可能從任何分解開始。

null 空間也是與特征值 0 相關聯的特征空間。如果矩陣值中存在噪聲(或只是數值錯誤),則不會有恰好為 0 的特征值(如您所知,數值矩陣在實踐中從來都不是完全奇異的。總會有一些數值錯誤)

我推測 scilab 中的“公差”是:特征值或類似值的最大值。 閱讀之后,我發現 scilab 默認依賴 SVD 分解來提取 kernel 之類的東西。因此, tol可能是奇異值的最大值(即 Mᵀ·M 的特征值的平方根)。 Null 空間是與“足夠空”的奇異值匹配的 V 線的跨度。

所以,也許你應該對Eigen做同樣的事情:執行 SVD。 然后是 V 的 select 行(或列,具體取決於庫。有些返回 V,有些返回 Vᵀ)匹配對你來說足夠小的奇異值。

例如,在 python 中(抱歉,我既沒有scilab也沒有Eigen 。我知道我回答這個問題很奇怪。但這是更多的線性代數問題,沒有其他人回答:D)。

import numpy as np
import scipy

# Same matrix
M=np.array([[-0.000004,   0.0000376, -0.0000261],
            [-0.0000017, -0.459682,   0.84146  ],
            [ 0.0000458, -0.841457,  -0.459684 ]])

scipy.linalg.null_space(M)
# returns array([], shape=(3, 0), dtype=float64)
# Same problem: no null space

np.linalg.eig(M)
# Returns
# (array([-3.99909409e-06+0.j       , 
#         -4.59683000e-01+0.8414585j,
#         -4.59683000e-01-0.8414585j]),
# array([[ 9.99999999e-01+0.00000000e+00j, -3.01853493e-05-1.51067336e-05j, -3.01853493e-05+1.51067336e-05j],
#        [ 4.10693606e-05+0.00000000e+00j,  7.07107411e-01+0.00000000e+00j,  7.07107411e-01-0.00000000e+00j],
#        [ 2.44559237e-05+0.00000000e+00j, -8.40775572e-07+7.07106151e-01j, -8.40775572e-07-7.07106151e-01j]]))

# No 0 eigen value. But you may think that the first one is small enough.
# Therefore, the associated eigen vectors are a basis for a "almost null space"
# So here, "almost null-space" is the span of first column
# That is [1, 4.11×10⁻⁵, 2.45×10⁻⁵]

# Using SVD
np.linalg.svd(M)
# Returns
#(array([[-2.54689055e-05,  4.03741349e-05, -9.99999999e-01],
#        [ 8.55645091e-01, -5.17563016e-01, -4.26885031e-05],
#        [-5.17563018e-01, -8.55645091e-01, -2.13641668e-05]]),
# array([9.58834879e-01, 9.58831275e-01, 3.99909409e-06]), 
# array([[-2.62390131e-05,  4.39933685e-02,  9.99031823e-01],
#        [-3.99536921e-05,  9.99031822e-01, -4.39933695e-02],
#        [ 9.99999999e-01,  4.10693525e-05,  2.44559116e-05]]))

# No null singular value. But the last one is "null enough"
# So the "almost null space" is the span of the last row of V
# [ 9.99999999e-01,  4.10693525e-05,  2.44559116e-05]

編輯

剛才在文檔中看到python scipy的null_space也有一個tolerance參數。

所以scipy.linalg.null_space(M, 0.0001)返回

array([[9.99999999e-01],
       [4.10693525e-05],
       [2.44559116e-05]])

但是,更重要的是,我在null_space文檔中讀到它

使用 SVD 構造 A 的 null 空間的正交基

關於這種公差:

相對條件數。 小於 rcond * max(s) 的奇異值 s 被視為零。

所以,這是官方的。 至少對於 python scipy,一個 null 空間是匹配足夠小的奇異值的 Vᵀ 行的跨度。 與我之前的猜測唯一不同的是,它不是sᵢ<tol ,而是sᵢ<tol*max(s)來表征什么是“足夠小”。

所以,回到你的Eigen庫。 我會做同樣的事情。 計算 M 的 SVD 分解。然后 select V 行(或列,但如果文檔沒有說明是哪一個,請使用您的示例,看看它是在行還是列中找到您的 [1, 4.1×10⁻⁵, 2.4×10⁻⁵]) 匹配小於tol × bigger singular value

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM