简单线性依赖

问题描述

试图找到两个向量是线性相关还是独立的。我不断遇到错误“数组的最后两个维必须是正方形?有人可以解释吗?

def Indy2Vec(v1,v2):
    
    A = np.array([v1])
    B = np.array([v2])
    print(A)
    #A =np.linalg.matrix_rank(A)
    A=np.linalg.solve(A,B)
    
    return A


v1 = np.array([0,5,0])
v2 = np.array([0,-10,0])
v3 = np.array([1,2,3])
v4 = np.array([-2,-4,-6])
Indy2Vec(v1,v2)

解决方法

问题陈述不正确

看来您没有解决正确的问题。按照您的说法,它不能像您使用的method一样工作:

计算确定的(即全)的“精确”解x 秩,线性矩阵方程ax = b。

根据文档中的定义。

将您的问题写为Ax = b很诱人。但是随后您需要一个3x3矩阵来针对向量b=[0,0]T进行测试,并找到一个非平凡的解x来声明所有三个向量都不是线性独立的。但这将意味着矩阵没有完整的排名。

在您的代码中,以下表达式无法实现功能签名:

np.linalg.solve(np.array([v1]),v2)

并引发以下错误:

LinAlgError: Last 2 dimensions of the array must be square

根据矩阵形状,对numpy.linalg.solve的有效调用将是:

np.linalg.solve(np.array([v1,v2,v3]).T,np.zeros(v1.size))

但是以两种方式失败:

LinAlgError: Singular matrix

首先是因为矩阵不是满秩,因此不可逆。其次,这不能解决两个向量的问题。

一般解决方案

import numpy as np
from scipy import linalg

相反,您想解决关于linear independence的更一般的问题,可以通过评估[v1,v2]T的{​​{3}} 来解决:

在线性代数中,矩阵A的秩为 由其生成(或跨越)的向量空间的维数 列。这对应于线性最大 A的独立列。

使用numpy,您可以使用rank

np.linalg.matrix_rank(np.array([v1,v2]).T) # Missing dimension: 1
np.linalg.matrix_rank(np.array([v1,v3]).T) # Full rank: 2

该方法计算执行numpy.linalg.matrix_rank时计算出的空奇异值,SVD decomposition提供了该算法的实现:

U,s,V = linalg.svd(np.array([v1,v2]).T) # s = [11.18033989,0.]
U,v3]).T) # s = [5.55992016,2.84381571]

执行scipy.linalg.svd (例如使用Gauss Elimination)并检查结果。 Package scipy提供了LU decomposition

p,l,u = linalg.lu(np.array([v1,v2]).T) # Null pivot: u = [[5.,-10.],[0.,0.]]
p,v3]).T) # Full rank:  u = [[5.,2.],3.]]

所有这些方法都会评估从矩阵列跨越的向量空间的维数。如果矩阵是满秩的,那么您的向量是线性独立的。如果不是,则它们至少有两个从属向量。

那么解决问题的一种简单方法是:

def indep1(*args):
    A = np.array(args).T
    return np.linalg.matrix_rank(A) == len(args)

indep1(v1,v2) # False
indep1(v1,v3) # True
indep1(v1,v3) # False
indep1(v1,np.zeros(v1.size)) # False

特殊情况

如果您停留在3D向量空间中并且只需要检查两个向量,则还可以利用scipy.linalg.lu提供的cross product

np.cross(v1,v2) # Colinear: [0,0]
np.cross(v1,v3) # Not colinear: [15,-5]

更具体的选择是:

def indep2(a,b):
    return not np.allclose(np.cross(a,b),0.)

indep2(v1,v2) # False
indep2(v1,v3) # True
# indep2(v1,v3) # TypeError
indep2(v1,np.zeros(v1.size)) # False

恒定比率

根据@MadPhycist的建议,我们还可以评估以下事实:共线向量共享标量比例因子,例如a = k*b,那么一种非防弹测试的方法是检查坐标比例是否不变:

def indep3(a,b):
    r = a/b                                 # Ratio of coordinates
    q = np.isfinite(r)                      # Filter bad ratio (zero division)
    return not np.allclose(r[q],r[q][0])   # Assess all ratio are equal

indep3(v1,v2) # False
indep3(v1,v3) # True
# indep3(v3,np.zeros(v1.size)) # IndexError

如果与以前的解决方案相比需要较少的计算并且不依赖于高级别的线性代数,则需要处理特定的情况,并且建议的实现方式有些臭(不要使用)。

格拉姆方法

对于两个向量,可以安全地实现@dmuir公开的方法,如下所示:

def indep4(a,b):
    return not np.isclose(np.dot(a,b)*np.dot(b,a),np.dot(a,a)*np.dot(b,b))

indep4(v1,v2) # False
indep4(v1,v3) # True
indep4(v3,v4) # False
indep4(v3,np.zeros(v1.size)) # False
,

对两个向量的简单测试是: A和B是线性相关的iff

(A.B)*(A.B) == (A.A) * (B.B)

其中。是点积。

当然,在使用浮点算术时,您必须小心测试相等性。

这可以推广到更多的向量。 V [1] .. V [n]是线性相关的,前提是它们的Gramian G是奇异的,其中

G[i,j] = V[i].V[j] (i,j=1..N)
,

为什么不使用更简单的算法:

def is_linearly_dependent(a,b):
    non_zero = b != 0
    if len(np.unique(a[non_zero]/b[non_zero])) > 1:
        return False
    else:
        zero = np.logical_not(b)
        if np.any(a[zero] != 0):
            return False
    return True