Подтвердить что ты не робот

Вычисление нулевого пространства матрицы

Я пытаюсь решить набор уравнений вида Ax = 0. A - известная матрица 6x6, и я написал код ниже, используя SVD, чтобы получить вектор x, который работает в определенной степени. Ответ примерно правильный, но недостаточно для того, чтобы быть полезным для меня, как я могу улучшить точность вычисления? Опускание eps ниже 1.e-4 приводит к сбою функции.

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)
4b9b3361

Ответ 1

A - полный ранг, поэтому x 0

Поскольку похоже, что вам нужно решение наименьших квадратов, т.е. min ||A*x|| s.t. ||x|| = 1, выполните SVD таким образом, чтобы [U S V] = svd(A) и последний столбец V (предполагая, что столбцы отсортированы в порядке убывания особых значений) x.

I.e.,

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

Итак,

x =

    0.0050325
    0.0028357
   0.00013067
    0.0052698
      0.98402
      0.17788

И ||A*x|| = 0.00027528 в отличие от предыдущего решения для x, где ||A*x_old|| = 0.079442

Ответ 2

Внимание: может возникнуть путаница с SVD в python и matlab-синтаксисе (?): в python numpy.linalg.svd(A) возвращает матрицы u, s, v такие, что u * s * v = A (строго: точка (u, точка (diag (s), v) = A, так как s - вектор, а не двумерная матрица в numpy).

Самый верный ответ правилен в том смысле, что обычно вы пишете u * s * vh = A и vh возвращается, и в этом ответе обсуждается v AND NOT vh.

Короче говоря: если у вас есть матрицы u, s, v такие, что u * s * v = A, то последние строки v, а не последние кол-во v, описывают пустое пространство.

Изменить: [для таких людей, как я:] каждая из последних строк представляет собой вектор v0 такой, что A * v0 = 0 (если соответствующее сингулярное значение равно 0)