Почему numpy.linalg.solve() предлагает более точные инверсии матрицы, чем numpy.linalg.inv()?

Я не совсем понимаю, почему numpy.linalg.solve() дает более точный ответ, тогда как numpy.linalg.inv() несколько разрывается, давая (что я считаю) оценки.

Для конкретного примера я решаю уравнение C^{-1} * d, где C обозначает матрицу, а d - вектор-массив. Для обсуждения размеры C имеют форму (1000,1000), а d - форма (1,1000).

numpy.linalg.solve(A, b) решает уравнение A*x=b для x, т.е. x = A^{-1} * b. Поэтому я мог бы либо решить это уравнение с помощью

(1)

inverse = numpy.linalg.inv(C)
result = inverse * d

или (2)

numpy.linalg.solve(C, d)

Метод (2) дает гораздо более точные результаты. Почему это?

Что именно происходит, так что один "работает лучше", чем другой?

Ответы

Ответ 1

np.linalg.solve(A, b) не вычисляет обратное значение A. Вместо этого он вызывает одну из подпрограмм LAPACK, которая сначала разлагает A на разложение LU, а затем решает для x использование прямого и обратного замещения (см. здесь).

np.linalg.inv использует тот же метод для вычисления инверсии A путем решения для A -1 в A · A -1 = I, где я - тождество *. Шаг факторизации точно такой же, как указано выше, но для A -1 (матрица n × n) требуется больше операций с плавающей запятой, чем для x (вектор n-длинного вектора). Кроме того, если затем вы хотите получить x с помощью тождества A -1 · b = x, тогда дополнительное умножение матриц потребует еще большего числа операций с плавающей запятой, а следовательно, более низкой производительности и большей числовой ошибки.

Нет необходимости в промежуточном этапе вычисления A -1 - быстрее и точнее получить x напрямую.


* Соответствующий бит источника для inv здесь здесь. К сожалению, это немного сложно понять, поскольку он шаблонизирован с C. Важно отметить, что единичная матрица передается решателю LAPACK в качестве параметра B.

Ответ 2

если мы реализуем код для вычисления матрицы, используя формулу (1/detA) * adjointA. по какой причине нет ошибки усечения?