Симпатичные упрощающие суммы на основе свободных параметров - PullRequest
1 голос
/ 29 апреля 2020

У меня есть симпозиум:

import sympy

x = sympy.IndexedBase('x')
n = sympy.symbols('n')
i = sympy.symbols('i', cls=sympy.Idx)

my_sum = sympy.summation(x[i], (i,1,n))

В моих различных вычислениях и тому подобном я иногда получаю вложенные суммы. Иногда эти суммы имеют «свободные переменные», а иногда нет. Например, я мог бы получить следующее:

my_double_sum = sympy.summation(my_sum, (i,1,n))

Теперь, поскольку my_sum не имеет "свободного" i от внешней суммы, то это должно упроститься до :

n*Sum(x[i], (i, 1, n))

Однако, sympy.simplify(my_double_sum) дает:

Sum(x[i], (i, 1, n), (i, 1, n))

Как я могу sympy разумно упростить суммирование по индексам свободных слагаемых?

1 Ответ

1 голос
/ 30 апреля 2020

Это поведение выглядело немного странно. Вот почему это происходит (и посмотрите, что является ошибкой, а что нет).


Во-первых, summation - это просто синтактический c сахар для создание Sum и запуск .doit(). Sum 'doit использует среди остальных eval_sum, который извлекает предельные границы, когда предельная переменная не является свободной переменной функции, и простая проверка показывает, что действительно это должно быть здесь! (и, как вы показали, это не так):

>>> i in my_sum.free_symbols
False

, поэтому я немного покопался в модуле summation.

Теперь, Sum имеет родителя с именем AddWithLimits. В своем создателе класса он использует функцию _common_new, которая отменяет функцию, которую он получает .

Это превращает Sum(Sum(x[i], (i, 1, n)), (i, 1, n)) в Sum(x[i], (i, 1, n), (i, 1, n)) (задолго до вызова doit), поэтому внутренняя функция - x[i], а не объект Sum, который вы определили в my_sum (который не ' t всплывает с первого взгляда), , поэтому предельная переменная фактически является свободной переменной функции .


Я пытался вручную отменить денестирование , комментируя три строки под комментарием # denest any nested calls, и действительно, я получил

n*Sum(x[i], (i, 1, n))

Конечно, простое изменение, которое, вероятно, повредило бы другие части кода, поскольку деенестирование предполагается во многих других ExprWithLimits функции. Является ли это предполагаемым поведением, можно утверждать в пользу , но если вы считаете, что его следует охватить, его, вероятно, следует явно указать внутри eval_sum как особый случай.


Тем не менее, я ожидаю, что суммирование с другой переменной будет обычно упрощено, как

summation(x[i], (i, 1, n), (j, 1, n))

, что не так. Я подозреваю, что это больше предполагаемого поведения (что вызвано тем, что первая итерация по eval_sum возвращает None, поэтому пропускает расширение символа j).

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