Ask Your Question

How to define functions with varying number of variables

asked 2021-05-02 21:54:48 +0200

tamandua gravatar image

I want to compute the Frechet derivative for a vector field, and that code works perfectly for functions with two variables x and t.

var ("t x")
v  = function ("v")
u  = function ("u")
w1 = function ("w1")
w2 = function ("w2")
eqsys = [diff(v(x,t), x) - u(x,t), diff(v(x,t), t) - diff(u(x,t), x)/(u(x,t)**2)]

def FrechetD (support, dependVar, independVar, testfunction):
    frechet = []
    eps = var ("eps")
    v = independVar[:] + [eps]
    for j in range (len(support)):
        deriv = []
        for i in range (len(support)):
            r0 (x, t, eps) =  dependVar[i](*independVar)+ testfunction[i](*independVar) * eps
            s  =  support[j].substitute_function (dependVar[i], r0)
            deriv.append (diff(s, eps).subs ({eps: 0}))
        frechet.append (deriv)
    return frechet
FrechetD (eqsys, [u,v], [x,t], [w1,w2])
[[-w1(x, t), diff(w2(x, t), x)],
 [2*w1(x, t)*diff(u(x, t), x)/u(x, t)^3 - diff(w1(x, t), x)/u(x, t)^2,
  diff(w2(x, t), t)]]

but my problem is the line

r0 (x, t, eps) =  dependVar[i](*independVar)+ testfunction[i](*independVar) * eps

because this depends on the hardcoded x and t. Without it the following derivation for eps always is 0. Even when I add someting like

_r0 = function('ro')(*v)

doesn't work. What i want to do is to something like

r0 (*v) =  dependVar[i](*independVar)+ testfunction[i](*independVar) * eps

to get rid of the hardcoded variables and/or the number of variables. Is that possible ?

edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted

answered 2021-05-03 05:12:20 +0200

dsejas gravatar image

Hello, @tamandua! I feel embarrassed to admit this is the first time I hear about the Fréchet derivative, thus I am not sure about what you are trying to achieve or how to test my code. However, I hope the following is useful for you.

On one hand, Sage's function() allows to define symbolic functions (referring to "function" in the mathematical sense). (Sorry about the repetitive words). In this particular case, I don't think you need such a thing, since the instructions you used to work with r0 work perfectly well with normal Python functions (this time, "function" in the sense of "subroutine"). For example, you could just define inside your innermost loop the following:

def r0(*args):
    return dependVar[i](*independVar)+ testfunction[i](*independVar) * eps

and that should do the trick.

On the other hand, it is also possible to define a symbolic function with an arbitrary number of arguments, as you request in your question. For completeness (and for other users with this same question), I am going to describe what you should do. First, define a Python subroutine that accepts an arbitrary number of arguments. This is basically the same as my previous bit of code, but I will use a different name in order to avoid name clash. For example,

def _r0(*args):
    return dependVar[i](*independVar)+ testfunction[i](*independVar) * eps

Now, you create a symbolic function r0 and indicate Sage that its values should be computed using the _r0 subroutine:

r0 = function('r0', eval_func=_r0)

That's it!

If you want to know more about Sage's function(), you can use the command function?, and you will be able to see the documentation of this command. In fact, it is way more advanced and complex than I can describe here. For example, you can actually define the symbolic function r0 and how to differentiate it symbolically.

In any case, here are the two versions of my code:

Please, let me know if this worked for you. I recommend you test it with different case, just to be sure. If it doesn't work, please, let me know so we can work an more adequate approach for your use!

I hope this helps!

edit flag offensive delete link more


Owe you some beer!

Both version work as expected. And also your explanation is very helpful.

I had implemented the classical "can't see the forest for the trees" pattern which hindered me to use the most natural python solution : a simple "def r0 (*args)".

THX a lot.

PS: Frechet derivative is a generalisation of the standard directional derivative which puts a weight (w1, w2 in the example) on the steepest descent. The Gateaux derivative generalizes the Frechet derivative to locally convex topological vector spaces like Banach spaces.

tamandua gravatar imagetamandua ( 2021-05-04 12:36:10 +0200 )edit

Hello, @tamandua! I'm happy to help! Thank you for the information about the Frechet and Gateaux derivatives. It is always great to learn something new!

dsejas gravatar imagedsejas ( 2021-05-10 03:30:36 +0200 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2021-05-02 21:54:48 +0200

Seen: 352 times

Last updated: May 03 '21