# How to dynamically substitute a variable in a callable function?

Hi guys, this is a little problem I came across a week ago.

I'm trying to define a python function that accepts:
1. a callable sage function (of potentially more than one variable) as the first argument (henceforth called func), and
2. a symbolic variable as the second argument (henceforth called xsub)

My function then needs to define a dummy symbolic variable (t), and substitute xsub with t in func.
I can do this for one variable equations in current 4.8 sagemath, by ignoring the new substitution syntax, but it throws up a depreciation warning (Which I'm assuming will become an error in 5.0).

Here's what my code looks like:

def fracintegral(func,xsub,n,a=0):
var('t')
assume(x>a)
assume(t>a)
return integrate((x-t)^(n-1)*func(t),t,a,x)

The last line should look something like:

    return integrate((x-t)^(n-1)*func(x=t),t,a,x)
in order to avoid Depreciation Warnings, but this hardcodes x as the variable to be substituted. (Useless if my func is a y function.)

If I try:

    return integrate((x-t)^(n-1)*func(xsub=t),t,a,x)

then substitution of func(x=t) doesn't occur (and the integrate function effectively treats func as a constant with respect to dt).

Trying:

    return integrate((x-t)^(n-1)*func.subs(xsub==t),t,a,x)
doesn't work either, same result as func(xsub=t).

So, any idea how a function can accept a symbolic variable, and dynamically substitute out that variable in a callable function?

edit retag close merge delete

On an unrelated note, you may want to see if there is a way to do this without redeclaring t each time. Does that remove the assumptions on t? You can debug this with assumptions(). My first guess would be that it doesn't... but I could be wrong. Even after having spent a lot of time with our assumptions code, I still don't fully understand how it interacts with Maxima.

( 2012-03-26 23:25:42 +0200 )edit

Sort by ยป oldest newest most voted

Are you thinking of something like this?

def fracintegral(func,xsub,n,a=0):
t = var('t')
assume(x>a)
assume(t>a)
return integrate((x-t)^(n-1)*func.subs({xsub:t}),t,a,x)


which gives a deprecation-free

sage: var("x y")
(x, y)
sage: f1 = function("f", x)
sage: fracintegral(f1, x, 4)
-integrate((t - x)^3*f(t), t, 0, x)
sage: f2 = function("f", x, y)
sage: fracintegral(f2, y, 4)
-integrate((t - x)^3*f(x, t), t, 0, x)
sage: f3(x,y) = x^2+sin(y)
sage: fracintegral(f3, y, 4)
(x, y) |--> 1/4*x^6 + x^3 - 6*x + 6*sin(x)

more

Clever. So why doesn't func.subs(xsub=t) work, since that should be functionally equivalent?

( 2012-03-26 23:24:14 +0200 )edit

Maybe something to do with hashing of the xsub key in the dictionary?

( 2012-04-09 23:26:04 +0200 )edit

This solution is working for subs() but not for limit(). Could you give us please some explanation or link about what is really going in the background?

( 2013-09-17 08:09:08 +0200 )edit