sympy: объект 'Transpose' не имеет атрибута tolist
Я пытаюсь сделать некоторые символические матричные вычисления с sympy. Моя цель-получить символическое представление результата матричных вычислений. Я столкнулся с некоторыми проблемами, которые я свел к этому простому примеру, в котором я пытаюсь оценить результат возведения в степень указанной матрицы и умножения ее на произвольный вектор.
>>> import sympy
>>> v = sympy.MatrixSymbol('v', 2, 1)
>>> Z = sympy.zeros(2, 2) # create 2x2 zero matrix
>>> I = sympy.exp(Z) # exponentiate zero matrix to get identity matrix
>>> I * v
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "sympy/matrices/matrices.py", line 507, in __mul__
blst = B.T.tolist()
AttributeError: 'Transpose' object has no attribute 'tolist'
напротив, если я непосредственно создаю матрицу идентичности, а затем умножаю ее на v, то нет проблема:
>>> I_ = sympy.eye(2) # directly create the identity matrix
>>> I_ == I # check the two matrices are equal
True
>>> I_ * v
v
одна вещь, которую я отметил, заключается в том, что две матрицы идентичности имеют разные классы:
>>> I.__class__
sympy.matrices.immutable.ImmutableMatrix
>>> I_.__class__
sympy.matrices.dense.MutableDenseMatrix
Я также обнаружил, что вызов as_mutable()
метод обойти.
>>> I.as_mutable() * v
v
всегда ли надо ставить as_mutable()
вызовы на протяжении всех вычислений линейной алгебры? Я предполагаю, что нет, и что вместо этого эти ошибки предполагают, что я использую неправильную стратегию для решения своей проблемы, но я не могу понять, какая правильная стратегия должен быть. У кого-нибудь есть указания?
Я прочитал страницу документации на Неизменяемые Матриц но я все равно мог бы помочь понять, как важны их различия со стандартными изменяемыми матрицами и почему некоторые операции (например, sympy.exp) преобразование между этими различными классами.
1 ответов
я бы сказал, что это ошибка в Sympy:
в Python, вы можете перегрузка оператора умножения с обеих сторон. A*B
может внутренне обрабатываться либо вызовом A.__mul__(B)
или B.__rmul__(A)
. Первые вызовы Python A.__mul__
, а если этот метод не существует или возвращает NotImplemented
, затем Python пытается B.__rmul__
автоматически. SymPy вместо этого использует декоратора под названием call_highest_priority чтобы решить, какую из обеих реализаций использовать. Это выглядит вверх _op_priority
соответствующих классов и вызывает функцию реализации с более высоким приоритетом. Приоритеты в вашем случае 11 для v
и I
и 10.01 на I_
, так что I
предпочтительнее. Кроме того, базовая реализация __mul__
, который I
использует, не хватает декоратор.
короче, I*v
в конечном итоге всегда звонит I.__mul__
и __mul__
не может обрабатывать MatrixSymbol
s, но не возвращается NotImplemented
либо. v.__rmul__(I)
работает ожидаемый.
правильным решением было бы захватить AttributeError
на matrices.py
и возврат NotImplemented
, то есть
try:
blst = B.T.tolist()
except AttributeError:
return NotImplemented
Python автоматически вернется к __rmul__
. Hack'ish исправить было бы настроить _op_priority
. В любом случае, вы должны подать отчет об ошибке: если ошибка была по дизайну (то есть, если вы случайно попробовали что-то, что не должно работать), то сообщение об ошибке скажет так.