简体   繁体   English

使用 Eigen 库,我可以获得只有一个“近似”矩阵的 kernel 吗?

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

I need to find the kernel (aka null space) of a 3*3 matrix which is of full rank 3, but very close to being singular and thus of rank 2. This means it has no null space unless you look for it with some "tolerance".我需要找到一个 3*3 矩阵的 kernel(又名 null 空间),它的满秩为 3,但非常接近单数,因此是秩 2。这意味着它没有 null 空间,除非你用一些东西寻找它“宽容”。

In Scilab (which is a free and fewer-featured alternative to Matlab) I can do the following:在 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

However, when I go to C++, I don't know how to introduce the tolerance in Eigen:但是,当我go到C++时,我不知道如何在Eigen中引入容差:

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

What can I do?我能做什么?

I am not very familiar with Eigen library.我对Eigen库不是很熟悉。 But I know it can be used to perform many decomposition, but also to find eigen spaces (that would be surprising, if not, considering the name).但我知道它可用于执行许多分解,还可以用于查找特征空间(考虑到名称,如果没有,那将是令人惊讶的)。 For example using EigenSolver , or probably starting from any decomposition.例如使用EigenSolver ,或者可能从任何分解开始。

A null space is also the eigen space associated with eigen value 0. If there is a noise in the matrix values (or just a numerical error), then, there won't be an exactly 0 eigen value (as you know, a numerical matrix is in practice never exactly singular. There is always some numerical error) null 空间也是与特征值 0 相关联的特征空间。如果矩阵值中存在噪声(或只是数值错误),则不会有恰好为 0 的特征值(如您所知,数值矩阵在实践中从来都不是完全奇异的。总会有一些数值错误)

And I surmise that the "tolerance" in scilab, is that: the maximum value of the eigen value or something similar.我推测 scilab 中的“公差”是:特征值或类似值的最大值。 After some reading, I see that scilab relies on SVD decomposition by default to extract things like kernel. So, tol is probably the maximum values of singular values (that is square roots of eigen values of Mᵀ·M.).阅读之后,我发现 scilab 默认依赖 SVD 分解来提取 kernel 之类的东西。因此, tol可能是奇异值的最大值(即 Mᵀ·M 的特征值的平方根)。 Null space being the span of the V lines matching the "null enough" singular values. Null 空间是与“足够空”的奇异值匹配的 V 线的跨度。

So, maybe you should do the same with Eigen : perform a SVD.所以,也许你应该对Eigen做同样的事情:执行 SVD。 And then select rows (or columns, depending on the libraries. Some return V, some other return Vᵀ) of V matching singular values small enough for you.然后是 V 的 select 行(或列,具体取决于库。有些返回 V,有些返回 Vᵀ)匹配对你来说足够小的奇异值。

For example, in python (sorry, I don't have neither scilab nor Eigen . I know it is then strange that I answer this question. But that is more linear algebra problem, and no one else is answering:D).例如,在 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]

Edit编辑

Just now, I saw in a documentation that python scipy's null_space has also a tolerance parameter.刚才在文档中看到python scipy的null_space也有一个tolerance参数。

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

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

But, more importantly, I read in null_space documentation that it但是,更重要的是,我在null_space文档中读到它

Construct an orthonormal basis for the null space of A using SVD使用 SVD 构造 A 的 null 空间的正交基

And about this tolerance:关于这种公差:

Relative condition number.相对条件数。 Singular values s smaller than rcond * max(s) are considered zero.小于 rcond * max(s) 的奇异值 s 被视为零。

So, it is official.所以,这是官方的。 At least for python scipy, a null space is the span of rows of Vᵀ matching a singular value small enough.至少对于 python scipy,一个 null 空间是匹配足够小的奇异值的 Vᵀ 行的跨度。 The only difference with my previous speculations is that it is not sᵢ<tol , but sᵢ<tol*max(s) that characterize what is "small enough".与我之前的猜测唯一不同的是,它不是sᵢ<tol ,而是sᵢ<tol*max(s)来表征什么是“足够小”。

So, back to your Eigen library.所以,回到你的Eigen库。 I would do the exact same.我会做同样的事情。 Compute a SVD decomposition of M. And then select the V rows (or columns, but if the documentation does not say which one, just use your example, and see if it is in a row or a column that you find your [1, 4.1×10⁻⁵, 2.4×10⁻⁵]) matching singular value smaller than tol × bigger singular value .计算 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