Reputation: 3491
I am trying to generate some random expressions in the form f(g(x))
. I'd like to be able to replace g
with something like sin(x)
or x**2
and f
with something like cos(x)
or log(x)
. So I'd get something like sin(cos(x))
or log(x**2)
(but randomized).
The part of this task I'm having trouble with is replacing both an outer and inner function.
Here's my code:
import sympy
from sympy import abc
x = abc.x
f = sympy.Function('f')(x)
g = sympy.Function('g')(x)
full=f.subs(x, g)
newExpr = sympy.sin(x)
newExpr2 = sympy.cos(x)
print(full)
replaced_inner = full.subs(g, newExpr)
print(replaced_inner)
both = replaced_inner.subs(f, newExpr2)
print(both)
full
prints f(g(x))
so that works
replaced_inner
prints f(sin(x))
so that works as well
both
prints f(sin(x))
when I want it to print cos(sin(x))
I've tried using args[0]
and f.func
but haven't made progress.
How can I replace both the inner and outer functions (and eventually more complex things like f(g(h(x)))
.
I could simply create cos(sin(x))
but I want to do it using variables so I can randomize what function gets replaced.
Upvotes: 3
Views: 2007
Reputation:
The problem is in confusion of functions like sympy.Function('f')
and expressions like sympy.Function('f')(x)
. Having defined f = sympy.Function('f')(x)
you made f
the expression f(x)
. And since
the expression f(g(x))
does not have f(x)
as a subexpression, attempted substitution fails.
All this is fixed if you work with actual functions, not plugging x
in prematurely.
f = sympy.Function('f')
g = sympy.Function('g')
full = f(g(x))
newExpr = sympy.sin
newExpr2 = sympy.cos
print(full)
replaced_inner = full.subs(g, newExpr)
print(replaced_inner)
both = replaced_inner.subs(f, newExpr2)
print(both)
This prints
f(g(x))
f(sin(x))
cos(sin(x))
Aside: you may also be interested in replace
method which supports certain patterns. Not necessary here, but may be necessary for more advanced replacements.
Upvotes: 2