Home > Software design >  How to use sympy to convert all standalone integers in an expression that aren't exponents to 1
How to use sympy to convert all standalone integers in an expression that aren't exponents to 1

Time:08-05

Is there a way to use sympy to find/replace all standalone integers (that aren't exponents) to 1.

For example, converting the following:

F(x) = (2/x^2)   (3/x^3)   4

To:

F(x) = (1/x^2)   (1/x^3)   1

I've searched extensively on stackoverflow for sympy expression.match/replace/find solutions, and have tried using a Wildcard symbol to find and replace all numbers in the expression but I keep running into the issue of matching and replacing the exponents (2 and 3 in this example) as well as they are also considered numbers.

Is there a simple (pythonic) way to achieve the above?

Thanks!

CodePudding user response:

setdefault used with replace is a nice way to go. The single expression below has 3 steps:

  1. mask off powers and record
  2. change Rationals to 1 (to handle integers in numer or denom)
  3. restore powers
>>> from sympy.abc import x
>>> from sympy import Dummy
>>> eq = (2/x**2)   (3/x**3)   4   1/x/8
>>> reps = {}
>>> eq = eq.replace(lambda x: x.is_Pow, lambda x: reps.setdefault(x, Dummy())
          ).replace(lambda x: x.is_Rational, lambda x: 1
          ).xreplace({v:k for k,v in reps.items()})
1   1/x   1/x**2   1/x**3

CodePudding user response:

You can write a function that will recurse into your expression. For any expression expr, expr.args will give you the components of that expression. expr.is_constant() will tell you if it's a constant. expr.is_Pow will tell you if it's an exponential expression, so you can choose not to drill down into these expressions.

import sympy

def get_constants(expr):
    c = set()
    for x in expr.args:
        if x.is_constant(): c |= {x}
        if not x.is_Pow:
            c |= get_constants(x)
            
    return c

Now, you can get all the constants in said expression, and replace each of these constants using expr.replace().

def replace_constants(expr, repl):
    for const in get_constants(expr):
        expr = expr.replace(const, repl)

    return expr

With your example expression, we get:

x = sympy.symbols('x')
F = 2/x**2   3/x**3   4

G = replace_constants(F, 1)

print(F)    #   4   2/x**2   3/x**3
print(G)    #   1   x**(-2)   x**(-3)
  • Related