2016-05-04 6 views
3

У меня есть матрица 4x4 A с довольно длинными, но простыми символическими выражениями в каждой из ее записей. В нем задействовано около 30 различных символов. Под «простым» я подразумеваю, что эти символы объединены с использованием только сложения/вычитания, умножения/деления и целых чисел полномочий. Под «long» я имею в виду, что если я распечатаю матрицу, она покрывает три или четыре экрана.Ускорение вычисления символической детерминанты в SymPy

Мне нужен определитель этой матрицы. Или, если быть более конкретным, я знаю, что определитель является полиномом четвертого порядка в одном конкретном символе, и мне нужны коэффициенты этого многочлена. A.det() не заканчивается после нескольких часов работы, поэтому мне нужен другой подход. Есть идеи? До сих пор я старался делать различные функции simplify у каждого элемента A без каких-либо успехов.

Есть ли какая-то стратегия, которую я могу использовать, чтобы Sympy мог знать о простой структуре моих выражений или что я знаю, что результат является полиномом в одном из символов?

+0

@Meta: Нет, записи могут быть произвольными суммами, произведениями и целыми степенями этого символа. – gspr

+0

@Meta: Нет, я допускаю и отрицательные полномочия символа, так что это не полином. Может быть, полиномиальный модуль SymPy все же может справиться с этим? В общем случае, записями являются * отношения * многочленов от конкретного символа. – gspr

+1

@Meta: Разве это не смущает удалять комментарии? Теперь у меня нет никакого смысла. Во всяком случае: типичная матрица составляет 4400 символов при распечатке ... Я не думаю, что публикация здесь имеет смысл. – gspr

ответ

2

Может быть, это будет работать, чтобы создать общее выражение для 4x4 определителя

In [30]: A = Matrix(4, 4, symbols('A:4:4')) 

In [31]: A 
Out[31]: 
⎡A₀₀ A₀₁ A₀₂ A₀₃⎤ 
⎢     ⎥ 
⎢A₁₀ A₁₁ A₁₂ A₁₃⎥ 
⎢     ⎥ 
⎢A₂₀ A₂₁ A₂₂ A₂₃⎥ 
⎢     ⎥ 
⎣A₃₀ A₃₁ A₃₂ A₃₃⎦ 

In [32]: A.det() 
Out[32]: 
A₀₀⋅A₁₁⋅A₂₂⋅A₃₃ - A₀₀⋅A₁₁⋅A₂₃⋅A₃₂ - A₀₀⋅A₁₂⋅A₂₁⋅A₃₃ + A₀₀⋅A₁₂⋅A₂₃⋅A₃₁ + A₀₀⋅A₁₃⋅A₂₁⋅A₃₂ - A₀₀⋅A₁₃⋅A₂₂⋅A₃₁ - A₀₁⋅A₁₀⋅A₂₂⋅A₃₃ + A₀₁⋅A₁₀⋅A₂₃⋅A₃₂ + A₀₁⋅A₁₂⋅A₂₀⋅ 
A₃₃ - A₀₁⋅A₁₂⋅A₂₃⋅A₃₀ - A₀₁⋅A₁₃⋅A₂₀⋅A₃₂ + A₀₁⋅A₁₃⋅A₂₂⋅A₃₀ + A₀₂⋅A₁₀⋅A₂₁⋅A₃₃ - A₀₂⋅A₁₀⋅A₂₃⋅A₃₁ - A₀₂⋅A₁₁⋅A₂₀⋅A₃₃ + A₀₂⋅A₁₁⋅A₂₃⋅A₃₀ + A₀₂⋅A₁₃⋅A₂₀⋅A₃₁ - A₀₂⋅A₁ 
₃⋅A₂₁⋅A₃₀ - A₀₃⋅A₁₀⋅A₂₁⋅A₃₂ + A₀₃⋅A₁₀⋅A₂₂⋅A₃₁ + A₀₃⋅A₁₁⋅A₂₀⋅A₃₂ - A₀₃⋅A₁₁⋅A₂₂⋅A₃₀ - A₀₃⋅A₁₂⋅A₂₀⋅A₃₁ + A₀₃⋅A₁₂⋅A₂₁⋅A₃₀ 

, а затем заменить в записи с чем-то вроде

A.det().subs(zip(list(A), list(your_matrix))) 

SymPy медлительности для генерации 4x4 определитель является ошибка. Вы должны сообщить об этом в https://github.com/sympy/sympy/issues/new.

EDIT (это не будет вписываться в комментарии)

Похоже Matrix.det вызывает функцию упрощения. Для матриц 3x3 и меньше формула детерминанта выписывается явно, но для больших матриц она вычисляется с использованием алгоритма Bareis. Вы можете увидеть, где функция упрощения (cancel) называется here, что необходимо как часть вычисления, но в конечном итоге выполняет большую работу, потому что оно пытается упростить ваши очень большие выражения. Вероятно, было бы разумнее делать только упрощения, необходимые для отмены термина самого определителя. Для этого я открыл an issue.

Другая возможность ускорить это, что я не уверен, будет работать или нет, было бы выбрать другой алгоритм определения. Возможные значения: Matrix.det(method=alg), где alg является одним из "bareis" (по умолчанию), "berkowitz", или "det_LU".

+0

Вау! Метод 'det' должен делать некоторое неявное упрощение, потому что с вашим предложением весь процесс выполняется за считанные секунды. Благодаря! – gspr

+0

@gspr да, вы правы. См. Мое редактирование. – asmeurer

 Смежные вопросы

  • Нет связанных вопросов^_^