Переформатировать фрагменты выражений в SymPy, чтобы предотвратить распределение постоянного коэффициента - PullRequest
0 голосов
/ 11 ноября 2018

Предположим, я определил следующее выражение:

poly1 = 6/(25*(x + 3)) + 1/(5*(x + 3)**2)

который печатает:

6/(25*x + 75) + 1/(5*(x + 3)**2)

У меня есть два вопроса относительно этого выражения. Во-первых, есть ли способ сохранить выражение в том формате, в котором я его ввел? В частности, могу ли я что-то сделать, чтобы оставить знаменатель первого слагаемого как 25*(x + 3)?

Во-вторых, если у меня есть выражение в его печатной форме, каков наилучший способ разбить выражение, переформатировать знаменатель первого слагаемого и затем собрать его обратно? В идеале я мог бы просто копаться в выражении, используя серию вызовов args, чтобы добраться до знаменателя первого слагаемого, а затем использовать фактор-функцию, чтобы правильно его разложить, как в poly1.args[0].args[1].args[0].factor(). Проблема в том, что, поскольку кортежи, составляющие выражение, являются неизменяемыми, я не могу просто заменить фрагмент poly1 на выражение, вычисленное выше. Есть ли лучший способ заменить факторный полином, чем просто перестроить все выражение с нуля?

Примечание: я бы предпочел не использовать метод subs(), потому что он выполняет поиск по всему выражению, и может показаться, что могут быть случаи, когда вы захотите быть очень конкретными относительно различных частей, которые вы изменяете.

1 Ответ

0 голосов
/ 11 ноября 2018

Автоматическое распределение констант является раздражительной темой . Существует возможность отключить его следующим образом:

from sympy.core.evaluate import distribute
with distribute(False):
    poly1 = 6/(25*(x+3)) + 1/(5*(x + 3)**2)
    print(poly1)  #  6/(25*(x + 3)) + 1/(5*(x + 3)**2)

Или вы можете заключить 25 в UnevaluatedExpr, чтобы предотвратить его взаимодействие с другими терминами.

poly1 = 6/(UnevaluatedExpr(25)*(x+3)) + 1/(5*(x + 3)**2)
print(poly1)  #  6*25**(-1)/(x + 3) + 1/(5*(x + 3)**2)

Или используйте неоцененный продукт (Мул) в знаменателе:

poly1 = 6/Mul(25, x+3, evaluate=False) + 1/(5*(x + 3)**2)
print(poly1)  #  6/(25*(x + 3)) + 1/(5*(x + 3)**2)

Или оберните знаменатель в factor_terms - более мягкая форма factor, которая выполняет работу по извлечению коэффициента, не слишком путаясь с выражением.

poly1 = 6/factor_terms(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1)  #  6/(25*(x + 3)) + 1/(5*(x + 3)**2)

Или обмануть, введя символ, который выглядит как число:

c25 = symbols('25')
poly1 = 6/(c25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1)  #  1/(5*(x + 3)**2) + 6/(25*(x + 3))

Рекомендуемое чтение: Предотвратить оценку выражения

На второй вопрос о целевой замене сложно ответить в этой общности. Нужно рекурсировать через дерево выражений , перестроив expr как expr.func(*args), где args равны expr.args, возможно модифицированные. Основная проблема заключается в том, как вы узнаете, что этот экземпляр 25*x + 75 должен быть заменен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...