# Differentiating function with fluctuating number of variables

(Edit: I've changed the question somewhat - upon editing the code the problem seems to lie elsewhere.)

Let's say I have a vector space V of dimension n (which is variable) and a matrix M (also depending on n and other input), and I want to understand the derivative of the function v -> ||M*v|| at some vector v in V, and then evaluate it at tangent vectors.

As far as I can tell, the easiest way to do this is to use a symbolic vector v, then calculate ||M*v||, then take diff(), and then I can plug in a tangent vector.

So I would write something like

v = list(var('v_%d' % i) for i in range(1,n+1))
def f(*arg):
L = []
for var in arg:
L.append(var)
return (M*vector(L)).norm()


(which is clearly bad and going nowhere) but attempting something like this, diff(f) throws an error:

unable to convert <function f at 0x7f2b046c5b90> to a symbolic expression


Trying

f(*v) = (M*vector(v)).norm()


doesn't work either.

edit retag close merge delete

I can't replicate it, can you provide your code ? Or at least a working example that produces the issue.

( 2020-06-19 16:12:35 +0200 )edit

Oops, I've changed the question - thank you very much.

( 2020-06-19 17:18:47 +0200 )edit

Sort by » oldest newest most voted

diff only works on symbolic expression (elements of the symbolic ring SR), not on python objects like functions. But you are in luck because f(*v) is precisely an element of SR. So the correct syntax is f(*v).diff(v[i]).

As a side remark, f can be simplified a lot, by defining f = (M*vector(v)).norm(). In this case, f is a symbolic expression.

Here is a code that computes all the partial derivatives for some matrix M:

n = 3
v = list(var('v_%d' % i) for i in range(1, n+1))

M = Matrix([[1, 0, 0],
[0, 1, 0],
[0, 0, 1]])

f = (M*vector(v)).norm()

[diff(f, vi) for vi in v]


The output is:

[1/2*(v_1 + conjugate(v_1))/sqrt(abs(v_1)^2 + abs(v_2)^2 + abs(v_3)^2),
1/2*(v_2 + conjugate(v_2))/sqrt(abs(v_1)^2 + abs(v_2)^2 + abs(v_3)^2),
1/2*(v_3 + conjugate(v_3))/sqrt(abs(v_1)^2 + abs(v_2)^2 + abs(v_3)^2)]


Of course you can take the dot product of this list with any tangent vector.

more

Thanks so much; I'm struggling with the last step. If I set

v_1 = 1
v_2 = 2
v_3 = 3


Then how do I turn

[diff(f, vi) for vi in v]


into a list of numbers?

( 2020-07-26 02:50:50 +0200 )edit

Once the list is transformed into a vector you can use substitute, which is called like this:

sage: v = vector([diff(f, vi) for vi in v])
sage: v.substitute({v_1: 1, v_2: 2, v_3: 3})
(1/14*sqrt(14), 1/7*sqrt(14), 3/14*sqrt(14))

( 2020-07-26 22:29:40 +0200 )edit