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:
- mask off powers and record
- change Rationals to 1 (to handle integers in numer or denom)
- 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)