2010-06-07 17 views
11

Estoy intentando resolver un conjunto de ecuaciones de la forma Ax = 0. Se conoce una matriz de 6x6 y he escrito el código siguiente usando SVD para obtener el vector x que funciona para un cierto grado La respuesta es aproximadamente correcta, pero no lo suficientemente buena para ser útil para mí, ¿cómo puedo mejorar la precisión del cálculo? Al reducir los valores por debajo de 1.e-4, la función falla.Cálculo del espacio nulo de una matriz

from numpy.linalg import * 
from numpy import * 

A = matrix([[0.624010149127497 ,0.020915658603923 ,0.838082638087629 ,62.0778180312547 ,-0.336 ,0], 
[0.669649399820597 ,0.344105317421833 ,0.0543868015800246 ,49.0194290212841 ,-0.267 ,0], 
[0.473153758252885 ,0.366893577716959 ,0.924972565581684 ,186.071352614705 ,-1 ,0], 
[0.0759305208803158 ,0.356365401030535 ,0.126682113674883 ,175.292109352674 ,0 ,-5.201], 
[0.91160934274653 ,0.32447818779582 ,0.741382053883291 ,0.11536775372698 ,0 ,-0.034], 
[0.480860406786873 ,0.903499596111067 ,0.542581424762866 ,32.782593418975 ,0 ,-1]]) 

def null(A, eps=1e-3): 
    u,s,vh = svd(A,full_matrices=1,compute_uv=1) 
    null_space = compress(s <= eps, vh, axis=0) 
    return null_space.T 

NS = null(A) 
print "Null space equals ",NS,"\n" 
print dot(A,NS) 

Respuesta

9

A es de rango completo --- así x es

ya que parece que necesita una solución de mínimos cuadrados, es decir min ||A*x|| s.t. ||x|| = 1, hacer la SVD de tal manera que [U S V] = svd(A) y la última columna de V (suponiendo que las columnas estén ordenadas en orden de valores singulares decrecientes) es x.

Es decir,

U = 

    -0.23024  -0.23241  0.28225  -0.59968  -0.04403  -0.67213 
     -0.1818  -0.16426  0.18132  0.39639  0.83929  -0.21343 
    -0.69008  -0.59685  -0.18202  0.10908  -0.20664  0.28255 
    -0.65033  0.73984 -0.066702  -0.12447  0.088364  0.0442 
    -0.00045131 -0.043887  0.71552  -0.32745  0.1436  0.59855 
    -0.12164  0.11611  0.5813  0.59046  -0.47173  -0.25029 


S = 

     269.62   0   0   0   0   0 
      0  4.1038   0   0   0   0 
      0   0  1.656   0   0   0 
      0   0   0  0.6416   0   0 
      0   0   0   0  0.49215   0 
      0   0   0   0   0 0.00027528 


V = 

    -0.002597  -0.11341  0.68728  -0.12654  0.70622 0.0050325 
    -0.0024567  0.018021  0.4439  0.85217  -0.27644 0.0028357 
    -0.0036713  -0.1539  0.55281  -0.4961  -0.6516 0.00013067 
     -0.9999 -0.011204 -0.0068651 0.0013713 0.0014128 0.0052698 
    0.0030264  0.17515  0.02341 -0.020917 -0.0054032  0.98402 
    0.012996  -0.96557  -0.15623  0.10603  0.014754  0.17788 

Así,

x = 

    0.0050325 
    0.0028357 
    0.00013067 
    0.0052698 
     0.98402 
     0.17788 

Y, ||A*x|| = 0.00027528 en contraposición a la solución anterior para x donde ||A*x_old|| = 0.079442

+0

x = 0 es una solución al problema , pero poco interesante. La verdadera solución al problema, llegó por diferentes medios es: [0.880057009282733,0.571293018023548,0.0664250041765576,1,186.758799941964,33.7579819749057] T – Ainsworth

+0

¿Estás seguro? Veo algunos elementos distintos de cero en el resultado de 'A * x' ---' [-0.056356 -0.055643 -7.3896e-013 -0.0043278 0.004483 -2.1316e-014] ' – Jacob

+0

A menos, por supuesto, que no desee el espacio nulo, pero la solución de mínimos cuadrados, es decir 'min || A * x || S t. || x || = 1' – Jacob

5

Atención: Puede haber confusión con la SVD en pitón vs. matlab-sintaxis (?): en python, numpy.linalg.svd (A) devuelve matrices u, s, vs uch que u * s * v = A (estrictamente: punto (u, punto (diag (s), v) = A, porque s es un vector y no una matriz 2D en numpy).

La respuesta más alta es correcta en el sentido en que usualmente escribe u * s * vh = A y vh se devuelve, y esta respuesta discute v AND NOT vh.

Para hacer una larga historia corta: si tiene matrices u, s, v tal que u * s * v = A, entonces el último filas de v, no las últimas columnas de V, describir la espacio nulo.

Editar: [para gente como yo:] cada una de las últimas filas es una v0 vector tal que A * v0 = 0 (si el valor singular correspondiente es 0)

Cuestiones relacionadas