Избегайте сортировки аргументов в модуле Python Sympy

В настоящее время я разрабатываю дифференциальный оператор для sympy, который может быть помещается в матричную форму. В этом случае порядок списка args при создании объекта Mul очень важен, чтобы гарантировать выполнение дифференциации только там, где это требуется.

Проблема в том, что, когда делается следующее:

input = (t,z,x)
Mul(*input).args

Он возвращает (t, x, z), потому что произошла некоторая перестановка в args. Как избежать сортировки args?


person Saullo G. P. Castro    schedule 26.04.2013    source источник
comment
в реальном случае дифференциальный оператор применяется таким образом, что r*D(z)*z возвращает объект Mul, но в настоящее время он возвращает в следующем порядке (r, z, D(z)), что затрудняет правильное применение оператора. Подробнее см. здесь.   -  person Saullo G. P. Castro    schedule 26.04.2013
comment
Это очень похоже на stackoverflow.com/q/14624511/161801.   -  person asmeurer    schedule 27.04.2013


Ответы (1)


Почему порядок аргументов важен, чтобы он был правильным?

Единственный способ предотвратить это — сделать ваши символы некоммутативными (x = Symbol('x', commutative=False)). Объекты SymPy сравниваются путем сравнения args, поэтому для работы x*y*z == y*x*z аргументы должны быть отсортированы канонически. Были некоторые попытки заставить это работать без явной сортировки (в основном из соображений производительности), но обратите внимание, что даже если бы мы это сделали, не было бы никаких гарантий относительно порядка аргументов, особенно если вы выполняете какую-либо операцию над выражением. Очень часто функции перестраивают выражения в SymPy, которые обычно используют какой-то другой порядок, не связанный с оригиналом.

person asmeurer    schedule 26.04.2013
comment
Порядок args важен, чтобы избежать превращения Mul(*(r,D(z),z), который будет оцениваться позже, в r*z*D(z), потому что в последнем дифференциальный оператор D(z) не будет применяться должным образом. - person Saullo G. P. Castro; 27.04.2013
comment
Понимаю. Это фундаментальная проблема, о которой я говорил на stackoverflow.com/a/15482872/161801 (первый абзац). Прямо сейчас нет возможности контролировать то, что происходит внутри Mul в отношении пользовательских правил умножения. Лучшее, что вы можете получить, это то, что ваш оператор делает правильные вещи при умножении на *, и написать пользовательскую функцию, которая завершает работу над умножениями, применяемыми в противном случае. Учитывая проблему ассоциативности, которую я отметил в том же ответе, вам, вероятно, нужно будет просто использовать последнее решение. - person asmeurer; 27.04.2013
comment
Вот и все! Я использовал sympy.var('t, x, z', commutative=False), чтобы сделать x = Symbol('x', commutative=False) для всех, и теперь args не переделывается! Спасибо! - person Saullo G. P. Castro; 27.04.2013
comment
Что отличает Sage/Pynac? - person rwst; 15.12.2015