Как не считать двойные числа - PullRequest
1 голос
/ 07 марта 2020

Мне нужно, чтобы проект вычислял некоторую простоту некоторых выражений, и среди прочего мне нужно присвоить каждому числу, фигурирующему в выражении, сложность (что-то вроде log2 (x), такую, что сложность измеряется в битах т.е. log2 (4) = 2 бита). Во всяком случае, для выражения sympy у меня есть этот кусок кода:

is_atomic_number = lambda expr: expr.is_Atom and expr.is_number
eq_numbers = [subexpression for subexpression in preorder_traversal(expr) if is_atomic_number(subexpression)] 

В основном это работает, но если у меня есть что-то в форме 2 * (x + y), это возвращает как числа, появляющиеся в выражение (2,2) вместо просто 2, что я и хочу. Есть ли способ убедиться, что когда что-то учитывается, я считаю это только один раз? Спасибо!

1 Ответ

0 голосов
/ 07 марта 2020

Метод atoms может быть тем, что вам нужно:

>>> (2*(x+y)).atoms(Number)
{2}

В методе replace также есть опция отслеживания используемого отображения, но он не обрабатывает идентичные элементы, которые были заменены другими значениями

>>> (2*x + x**2).replace(lambda x:x.is_Number, lambda x: Dummy(), map=True)
(Dummy_1*x + x**Dummy_2, {2: Dummy_2})

Таким образом, может работать следующее:

>>> def flatargs(expr):
...     if expr.is_Atom: yield expr
...     else:
...         for a in expr.args:
...             for i in flatargs(a): yield i
>>> list(flatargs(2*x+x**2))
[x, 2, 2, x]
>>> from sympy.utilities.iterables import multiset
>>> multiset([i for i in flatargs(2*x+x**2+y/2) if i.is_Number)
{1/2: 1, 2: 2}

Если вы хотите, чтобы числитель и знаменатель были отдельно от flatargs, вам бы пришлось обрабатывать атом Rational как особый рассматривайте случаи, когда числитель или деноминатор равен 1. Но, надеюсь, то, что здесь, поможет вам в этом.

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