Для недоопределенной системы, такие, как ваши (ранг меньше числа переменных), mldivide
возвращает решение с так многими нулями насколько это возможно. Какая из переменных будет равна нулю, зависит от ее произвольного выбора.
В отличие от этого, метод возвращает lstsq
решение минимальной нормы в таких случаях: то есть, среди бесконечного семейства точных решений будет выбрать тот, который имеет наименьшую сумму квадратов переменных.
Итак, «специальное» решение Matlab несколько произвольно: в этой задаче можно установить любую из трех переменных в нуль. Решение, данное NumPy, на самом деле является более особенным: существует уникальное решение минимальной нормы.
Какое решение лучше для вашей цели, зависит от вашей цели. Неединственность решения обычно является поводом для пересмотра вашего подхода к уравнениям. Но так как вы спросили, вот код NumPy, который создает решения типа Matlab.
import numpy as np
from itertools import combinations
A = np.matrix([[1 ,2, 0],[0, 4, 3]])
b = np.matrix([[8],[18]])
num_vars = A.shape[1]
rank = np.linalg.matrix_rank(A)
if rank == num_vars:
sol = np.linalg.lstsq(A, b)[0] # not under-determined
else:
for nz in combinations(range(num_vars), rank): # the variables not set to zero
try:
sol = np.zeros((num_vars, 1))
sol[nz, :] = np.asarray(np.linalg.solve(A[:, nz], b))
print(sol)
except np.linalg.LinAlgError:
pass # picked bad variables, can't solve
Для примера он выводит три «специальное» решения, последние из которых является то, что выбирает Matlab.
[[-1. ]
[ 4.5]
[ 0. ]]
[[ 8.]
[ 0.]
[ 6.]]
[[ 0. ]
[ 4. ]
[ 0.66666667]]
Что вы подразумеваете под "специальным решением"? Решение из python ('[0.918 3.541 1.279]') также является правильным решением. У вас есть 2 уравнения в 3 unkowns, поэтому нет единственного решения. Решениями являются '[-1 9/2 0] + s * [3/2 -3/4 1]' для любого действительного числа 's'. Задайте 's = 2/3' для решения Matlab и' s = 1.27868852' для решения Python. – David
Это не просто предоставление правильного решения. mldivide всегда дает вектор решения n ненулевых элементов, где n - ранг матрицы, где numpy не делает этого. Я ищу, чтобы получить то же самое решение в numpy, как и mldivide. – Schrodinger
Решение Octave 'A \ b' такое же, как и« numpy ». Документ MATLAB предлагает «pinv (A) * B' как более дорогостоящий метод. В Октаве получается то же самое. 'numpy' также имеет' pinv', с тем же результатом. – hpaulj