I have the following function:
function make_automatic_xi(g_b)
function automatic_xi(Ψ, trajectory, tlist, n)
grad = Zygote.gradient(psi -> g_b(psi, trajectory, tlist, n), Ψ)[1]
if isnothing(grad)
return zero(Ψ) # g_b does not depend on Ψ
end
return -0.5 * grad
end
return automatic_xi
end
Applying this as
function g_b(Ψ, traj, tlist, n)
return real(dot(Ψ, traj.D * Ψ))
end
xi_auto = make_automatic_xi(g_b)
ξ1 = xi_auto(Ψ[1], trajectories[1], tlist, 1)
I get an ERROR: UndefRefError: access to undefined reference
Using g_b functions that don’t use traj work fine (but aren’t sufficiently general).
It did occur to me while I was writing this that this might be vaguely “problematic” in that I’m calling g_b with varying traj / n parameters in my program, not just varying Ψ — although for a particular derivative, traj, tlist, and n are constants.
I’ve long had other, “similar” code like this:
function make_gate_chi(J_T_U, trajectories; kwargs...)
function zygote_gate_chi(Ψ, trajectories)
function _J_T(U)
-J_T_U(U; kwargs...)
end
N = length(trajectories)
χ = Vector{eltype(Ψ)}(undef, N)
# We assume that that the initial states of the trajectories are the
# logical basis states
U = [trajectories[i].initial_state ⋅ Ψ[j] for i = 1:N, j = 1:N]
∇J = Zygote.gradient(gate -> _J_T(gate), U)[1]
for k = 1:N
χ[k] = 0.5 * sum([∇J[i, k] * trajectories[i].initial_state for i = 1:N])
end
return χ
end
return zygote_gate_chi
end
which always seems to work fine, and the only difference I see is that whenever I call the zygote_gate_chi, it is with the same trajectories variable, which also happens to be the same trajectories variable that was originally passed to make_gate_chi; even though that’s “coincidental” (make_gate_chi only gets trajectories due to some API requirements, it’s not actually used)
So I can’t quite put my finger on what exactly the difference is from Zygote’s perspective, or what approach I should take to make the original code work.
Apologies for these code snippets not being MWEs, but I was hoping someone might have some insights into Zygote’s internals based on the general structure of the code.