web-dev-qa-db-fra.com

Comment trouver des lignes linéairement indépendantes à partir d'une matrice

Comment identifier les lignes linéairement indépendantes d'une matrice? Par exemple,

enter image description here

La 4ème rangée est indépendante.

12
SparkAndShine

Premièrement, votre 3ème rangée dépend linéairement avec 1t et la 2ème rangée. Cependant, vos 1ère et 4ème colonnes sont linéairement dépendantes.

Deux méthodes que vous pouvez utiliser:

Valeur propre

Si l'une des valeurs propres de la matrice est égale à zéro, le vecteur propre correspondant est linéairement dépendant. La documentation eig stats les valeurs propres n'est pas forcément ordonnée. Je ne sais pas vraiment si la valeur propre dans le tableau résultant est simplement triée ou si elle a un ordre aléatoire. Cependant, en supposant que les valeurs propres correspondent à vos vecteurs de ligne, une méthode serait:

import numpy as np

matrix = np.array(
    [
        [0, 1 ,0 ,0],
        [0, 0, 1, 0],
        [0, 1, 1, 0],
        [1, 0, 0, 1]
    ])

lambdas, V =  np.linalg.eig(matrix.T)
# The linearly dependent row vectors 
print matrix[lambdas == 0,:]

Inégalité de Cauchy-Schwarz

Pour tester la dépendance linéaire des vecteurs et déterminer lesquels, vous pouvez utiliser l'inégalité Cauchy-Schwarz . Fondamentalement, si le produit intérieur des vecteurs est égal au produit de la norme des vecteurs, les vecteurs sont linéairement dépendants. Voici un exemple pour les colonnes:

import numpy as np

matrix = np.array(
    [
        [0, 1 ,0 ,0],
        [0, 0, 1, 0],
        [0, 1, 1, 0],
        [1, 0, 0, 1]
    ])

print np.linalg.det(matrix)

for i in range(matrix.shape[0]):
    for j in range(matrix.shape[0]):
        if i != j:
            inner_product = np.inner(
                matrix[:,i],
                matrix[:,j]
            )
            norm_i = np.linalg.norm(matrix[:,i])
            norm_j = np.linalg.norm(matrix[:,j])

            print 'I: ', matrix[:,i]
            print 'J: ', matrix[:,j]
            print 'Prod: ', inner_product
            print 'Norm i: ', norm_i
            print 'Norm j: ', norm_j
            if np.abs(inner_product - norm_j * norm_i) < 1E-5:
                print 'Dependent'
            else:
                print 'Independent'

Tester les lignes est une approche similaire.

Ensuite, vous pouvez étendre cela à l’essai pour tester toutes les combinaisons de vecteurs, mais j’imagine que cette solution est mal adaptée à la taille.

21
hakanc

Avec sympy vous pouvez trouver les lignes indépendantes linéaires en utilisant: sympy.Matrix.rref :

>>> import sympy 
>>> import numpy as np
>>> mat = np.array([[0,1,0,0],[0,0,1,0],[0,1,1,0],[1,0,0,1]])  # your matrix
>>> _, inds = sympy.Matrix(mat).T.rref()   # to check the rows you need to transpose!
>>> inds
[0, 1, 3]

Ce qui vous dit en gros que les lignes 0, 1 et 3 sont linéairement indépendantes alors que la ligne 2 ne l’est pas (combinaison linéaire des lignes 0 et 1).

Ensuite, vous pouvez supprimer ces lignes en découpant:

>>> mat[inds]
array([[0, 1, 0, 0],
       [0, 0, 1, 0],
       [1, 0, 0, 1]])

Cela fonctionne également bien pour les matrices rectangulaires (pas seulement pour les matrices quadratiques).

13
MSeifert

J'ai édité le code de l'inégalité de Cauchy-Schwartz qui s'adapte mieux à la dimension: les entrées sont la matrice et sa dimension, tandis que la sortie est une nouvelle matrice rectangulaire qui contient le long de ses lignes les colonnes linéairement indépendantes de la matrice de départ. Cela fonctionne dans l'hypothèse que la première colonne n'est jamais nulle, mais qu'elle peut être généralisée facilement afin de mettre en œuvre ce cas également. Une autre chose que j'ai observée est que 1e-5 semble être un seuil "flou", car certains vecteurs pathologiques particuliers se sont révélés être linéairement dépendants: 1e-4 ne me pose pas les mêmes problèmes. J'espère que cela pourrait être utile: il était assez difficile pour moi de trouver une routine qui fonctionne vraiment pour extraire les vecteurs li, et je suis donc disposé à partager le mien. Si vous trouvez un bug, merci de le signaler !!

from numpy import dot, zeros
from numpy.linalg import matrix_rank, norm

def find_li_vectors(dim, R):

    r = matrix_rank(R) 
    index = zeros( r ) #this will save the positions of the li columns in the matrix
    counter = 0
    index[0] = 0 #without loss of generality we pick the first column as linearly independent
    j = 0 #therefore the second index is simply 0

    for i in range(R.shape[0]): #loop over the columns
        if i != j: #if the two columns are not the same
            inner_product = dot( R[:,i], R[:,j] ) #compute the scalar product
            norm_i = norm(R[:,i]) #compute norms
            norm_j = norm(R[:,j])

            #inner product and the product of the norms are equal only if the two vectors are parallel
            #therefore we are looking for the ones which exhibit a difference which is bigger than a threshold
            if absolute(inner_product - norm_j * norm_i) > 1e-4:
                counter += 1 #counter is incremented
                index[counter] = i #index is saved
                j = i #j is refreshed
            #do not forget to refresh j: otherwise you would compute only the vectors li with the first column!!

    R_independent = zeros((r, dim))

    i = 0
    #now save everything in a new matrix
    while( i < r ):
        R_independent[i,:] = R[index[i],:] 
        i += 1

    return R_independent
6
Simone Bolognini

Je sais que cela a été demandé il y a quelque temps, mais voici une solution très simple. Pour un tableau, ce qui suit trouve un ensemble de vecteurs linéairement indépendants en ajoutant progressivement un vecteur et en testant si le rang a augmenté:

from numpy.linalg import matrix_rank

def LI_vecs(dim,mat):
    LI=[M[0]]
    for i in range(dim):
        tmp=[]
        for r in LI:
            tmp.append(r)
        tmp.append(M[i])                #set tmp=LI+[M[i]]
        if matrix_rank(tmp)>len(LI):    #test if M[i] is linearly independent from all (row) vectors in LI
            LI.append(M[i])             #note that matrix_rank does not need to take in a square matrix
    return LI                           #return set of linearly independent (row) vectors

#Example
mat=[[1,2,3,4],[4,5,6,7],[5,7,9,11],[2,4,6,8]]
LI_vecs(4,mat)
2
Couchy311

J'interprète le problème comme si on cherchait des lignes linéairement indépendantes des autres lignes. Cela revient à trouver des lignes qui dépendent linéairement d'autres lignes.

L'élimination gaussienne et traite les nombres inférieurs à un seuil comme des zéros peuvent le faire. Il est plus rapide que de rechercher les valeurs propres d'une matrice, de tester toutes les combinaisons de lignes avec une inégalité de Cauchy-Schwarz ou une décomposition en valeurs singulières.

Voir: https://math.stackexchange.com/questions/1297437/using-gauss-elimination-to-check-for-linear-dependence

Problème avec les nombres à virgule flottante:

http://numpy-discussion.10968.n7.nabble.com/Reduced-row-echelon-form-td16486.html

0
R zu