Sympy и Numpy не могут инвертировать матрицу, созданную с помощью Sympy - PullRequest
1 голос
/ 23 октября 2019

У меня есть уравнение, в котором есть символическая переменная с помощью пакета Sympy. используя эту переменную, я создал матрицу 6 * 6:

array([[1, exp(-0.04*a**2), exp(-0.16*a**2), exp(-0.36*a**2),
        exp(-0.64*a**2), exp(-1.0*a**2)],
       [exp(-0.04*a**2), 1, exp(-0.04*a**2), exp(-0.16*a**2),
        exp(-0.36*a**2), exp(-0.64*a**2)],
       [exp(-0.16*a**2), exp(-0.04*a**2), 1, exp(-0.04*a**2),
        exp(-0.16*a**2), exp(-0.36*a**2)],
       [exp(-0.36*a**2), exp(-0.16*a**2), exp(-0.04*a**2), 1,
        exp(-0.04*a**2), exp(-0.16*a**2)],
       [exp(-0.64*a**2), exp(-0.36*a**2), exp(-0.16*a**2),
        exp(-0.04*a**2), 1, exp(-0.04*a**2)],
       [exp(-1.0*a**2), exp(-0.64*a**2), exp(-0.36*a**2),
        exp(-0.16*a**2), exp(-0.04*a**2), 1]], dtype=object)

переменная выше является символом симпати. Теперь я хочу перевернуть эту матрицу. Используя numpy, я получаю следующую ошибку:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-117-3c958037db81> in <module>()
----> 1 inv(np.array(final_result))

D:\datascience\lib\site-packages\numpy\linalg\linalg.py in inv(a)
    526     signature = 'D->D' if isComplexType(t) else 'd->d'
    527     extobj = get_linalg_error_extobj(_raise_linalgerror_singular)
--> 528     ainv = _umath_linalg.inv(a, signature=signature, extobj=extobj)
    529     return wrap(ainv.astype(result_t, copy=False))
    530 

TypeError: No loop matching the specified signature and casting
was found for ufunc inv

и, используя собственный синтаксис Sympy для инверсии этой матрицы, то есть M ** -1, занимает слишком много времени и не вычисляет результаты. Есть ли способ инвертировать эту матрицу, используя numpy? или чистый синтаксис python?

Ответы [ 2 ]

2 голосов
/ 23 октября 2019

Если вы ищете символическое обратное, вам нужно использовать SymPy. NumPy вычисляет только обратные числа, и используемые им алгоритмы не будут работать с символьными матрицами.

Похоже, что алгоритм по умолчанию, используемый SymPy, работает медленно с этой матрицей, но вы можете попробовать альтернативные алгоритмы, передав ключевое слово method методу inv Matrix. Доступны следующие варианты: 'GE' (по умолчанию), 'LU' и 'ADJ'.

Это также может помочь сделать M.subs(exp(-a**2/25), b) для расчета. Таким образом, полученная матрица будет иметь степень b (вам нужно будет использовать рациональные числа вместо числа с плавающей запятой, чтобы это работало). Мне удалось получить обратное значение с помощью

a, b = symbols('a b')
M = Matrix([[1, exp(-a**2/25), exp(-4*a**2/25), exp(-9*a**2/25), exp(-16*a**2/25), exp(-a**2)], [exp(-a**2/25), 1, exp(-a**2/25), exp(-4*a**2/25), exp(-9*a**2/25), exp(-16*a**2/25)], [exp(-4*a**2/25), exp(-a**2/25), 1, exp(-a**2/25), exp(-4*a**2/25), exp(-9*a**2/25)], [exp(-9*a**2/25), exp(-4*a**2/25), exp(-a**2/25), 1, exp(-a**2/25), exp(-4*a**2/25)], [exp(-16*a**2/25), exp(-9*a**2/25), exp(-4*a**2/25), exp(-a**2/25), 1, exp(-a**2/25)], [exp(-a**2), exp(-16*a**2/25), exp(-9*a**2/25), exp(-4*a**2/25), exp(-a**2/25), 1]])
M2 = M.subs(exp(-a**2/25), b)
M2inv = simplify(M2.inv('ADJ')) # takes a little time to compute, about 1:30 on my machine
Minv = M2inv.subs(b, exp(-a**2/25))

. В конце дня вы можете подумать, нужна ли вам символическая инверсия матрицы. Достаточно ли заменить числовое значение на a, а затем вычислить обратное числовое значение с помощью NumPy? Вам действительно нужно обратное вообще? Обычно вычисление явной обратной матрицы не является хорошей идеей для численных расчетов. Обычно лучше использовать что-то вроде numpy.linalg.solve.

Символьные инверсии, как правило, являются очень сложными выражениями и по своей природе трудно поддаются вычислению. Числовые инверсии чрезвычайно численно нестабильны и почти никогда не являются хорошей идеей для вычисления любой проблемы, которую вы пытаетесь решить.

1 голос
/ 23 октября 2019

NumPy - это числовой пакет, который не может работать с символами SymPy. Если я правильно понимаю, вы используете a в качестве символа SymPy, не присваивая ему конкретное значение. Это делает вычисление обратного очень трудным. Для некоторых присвоений a матрица может даже не быть обратимой. Боюсь, что инверсия матрицы в SymPy не подходит для такой задачи. Что-то, что может немного помочь, это выражение чисел в виде дробей, потому что с реалами трудно работать символически.

Если вы попробуете то же самое с меньшими матрицами, вы заметите, что результат быстро превращается в сложный беспорядоксимволов. Вероятно, было бы проще численно инвертировать матрицу (с помощью NumPy) для каждого из значений a, которые вам нужны.

Еще один прием, который нужно попробовать, - это ввести вспомогательный символ для получения более простых выражений и затем подставить обратно. ,Например, сначала что-то вроде M.subs({a**2:-log(b)}). Полученную обратную матрицу проще упростить. Затем M.subs({b: exp(-a**2)}), чтобы выяснить, что происходит с оригинальной формулировкой. Простое вычисление определителя вашей исходной матрицы с помощью этой замены приводит к выражению длиной более 1000 символов, которое нелегко упростить. Остается мало надежд на то, что полная обратная матрица будет управляемым выражением.

...