# Automatic differentiation in different cases

I am trying to figure out :

1. how to automatically differentiate some function f(x1,x2,x3…) for vector of numbers. I want to use one package preferably , but if I have to mix, I want to mix zygote with ForwardDiff.

I think I have this down in using something like :

g(x,y)=x^2+y^2
ForwardDiff.gradient(z → g(z, z), [1.0, 2.0])

I guess if I wanted to take gradient for a vector, where I evaluate each partial derivative at the same point I could do :

X=[1.0,2.0,3.0]

for elem in X
end

This seems hacky and inefficient , and I know I can use static vectors to speed things up somewhat.

Next:

1. I want to evaluate a laplacian , a double gradient, for some multivariable function f(x1,x2,x3…) for a vector of numbers.

I guess I could chain the gradient function?

1. I want to evaluate a gradient f(x1,x2,x3,…) where I only evaluate for one variable, and I set say x2=1.0, x3=3.0

The way I have been doing this is grotesque , I simply recompile my function as a single variable function with a new global variable value put in for the x2,x3…

Thank you! I feel that this thread should be very useful.

I didn’t fully understand all those questions, but here is some code for ForwardDiff that can hopefully be helpful. Generally, I’d say it’s easier to work with functions `f(x)` where `x` is a vector, rather than functions `f(x1,x2,x3,...)` when using ForwardDiff. To make your future posts easier to read, include code in backticks ` (single for inline, triple for multiline).

``````using ForwardDiff
using StaticArrays
## --

# Function
f(x1,x2) = x1^2 + x2^2
f(x) = f(x,x)

∇f(x) = ForwardDiff.gradient( f , x )
∇f(x1,x2) = ∇f(SVector(x1,x2))

∇²f(x) = ForwardDiff.hessian( f , x )
∇²f(x1,x2) = ∇²f(SVector(x1,x2))

# Laplacian
f1(x) = ForwardDiff.derivative( x1 -> f(x1,x) , x )
f2(x) = ForwardDiff.derivative( x2 -> f(x,x2) , x )
f11(x) = ForwardDiff.derivative( x1 -> f1( SVector(x1,x) ) , x )
f22(x) = ForwardDiff.derivative( x2 -> f2( SVector(x,x2) ) , x )
Δf(x) = f11(x) + f22(x)
Δf(x1,x2) = Δf( SVector(x1,x2) )

# Evaluate

x1 = 1.0
x2 = 2.0

f(x1,x2)
∇f(x1,x2)
∇²f(x1,x2)
Δf(x1,x2)

# For a vector of numbers?

num_vec = [ SVector(rand(),rand()) for _ ∈ 1:5 ]

Δf.(num_vec)
``````

The code for the Laplacian is admittedly a little gnarly, if you want to do many higher-order directional derivatives, then TaylorDiff.jl is probably a better choice.

Laplacian is the trace of Hessian.

``````import LinearAlgebra:tr
g(x) = x^2*sin(x-x)
Δg=tr(ForwardDiff.hessian(g, [π/2, π/6]))
``````
1 Like