Reputation: 2012
Right now, to integrate a function fx
with SymPy I would do the following:
from sympy.abc import alpha as _alpha_, beta as _beta_, x as _x_
sym_args = _alpha_, _beta_
fx_definite_integral = sympy.integrate(fx(_x_, *sym_args), (_x_, xmin, xmax))
But this requires me to know beforehand what symbols I might need for a given function. But what if I plugged in a different function, with parameters, say, A, B, Y, Z, Q, W?
Instead of manually assigning symbols in SymPy, is there a way to generically assign symbols - basically, my sym_args
, based on the input function?
Ideally
sym_args = sympy.all_the_symbols_I_need_for_random_function(fx)
Upvotes: 2
Views: 277
Reputation: 59731
The problem is a bit ill-defined because, after all, you need to know something about the arguments of fx
, right? For example, fx
should have at least one argument for the x
; is it always the first argument, or the argument called x
, which may or may not be the first? Should the rest of arguments be given a specific sequence of names, such as alpha
, beta
, etc. or instead use symbols with the name of the argument? What if the arguments have default values?
I'll give one possible approach for a simple example, then you can choose how to implement it exactly for your case. Let's have this function:
def fx(x, a, b, c):
return x * (a + (b / c))
In order to extract information about the function arguments, you can use the inspect
import inspect
fx_args = inspect.getfullargspec(fx).args # fx_args <- ['x', 'a', 'b', 'c']
inspect.getfullargspec
returns a namedtuple
with information about the function arguments, you can check the docs to see if you need something else (e.g. to ignore parameters with default values). Now you can convert those to SymPy symbols:
import sympy
fx_argsym = sympy.symbols(fx_args) # fx_argsym <- [x, a, b, c]
Here you could use a different strategy. For example, if you wanted to have the first argument be always x
and the rest of arguments be always Greek letters (as long as you don't have too many arguments) you could do:
import sympy.abc
fx_argsym = [sympy.abc.x] + list(sympy.symbols(sympy.abc.greeks[:len(fx_args) - 1]))
# fx_argsym <- [x, alpha, beta, gamma]
You can manipulate fx_argsym
however you want to suit your needs. When you get get it right, you can call sympy.integrate
as usual:
fx_definite_integral = sympy.integrate(fx(*fx_argsym), (_x_, xmin, xmax))
Note that if you didn't make sure that x
was in fx_argsym
you may get an error, but that is easy to check for example with:
assert _x_ in fx_argsym
Upvotes: 1
Reputation: 91580
You can use
f = Function('f')
expr.Integral(f(x), (x, xmin, xmax))
and then use expr.replace(f, your_function)
to replace f
with your function. You will need to curry your_function
so that it accepts one parameter to match f
. As far as Integral
is concerned, it only needs to know that f
depends on x
. The rest of the (constant) variables can be "in" f
.
For instance, if your expression is x + A + B
, you can use expr.replace(f, lambda x: x + A + B)
.
Upvotes: 1