# 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