Hi everyone!
I’m trying to compute the gradient with respect to a certain circuit parameter and I would like to do it efficiently. I know there exist several efficient methods for this in Yao, i.e., faithful_grad() and expect’(). However, as far as I understand this computes the gradient with respect to all circuit parameters and I’m only interested in one particular parameter. At the moment, I’m doing it as follows:
const SINGLE_GATES = [Rx, Ry, Rz]
@const_gate ZZ = mat(kron(Z,Z))
rng = MersenneTwister()
randG = Random.Sampler(rng, SINGLE_GATES)
function circuit_layer(n::Int, β::Array{Float64, 1}, eps::Float64)
U = chain(n)
append!(U, chain(n, put(n, loc=>chain(rand(rng,randG)((2*rand())*eps*π))) for loc = 1:n))
for j = 1:n-1
append!(U, chain(n, put(n, (j,j+1)=>rot(ZZ, β[j]))))
end
return U
end
function cgrad_flayer(n::Int, β::Array{Float64, 1}, eps::Float64, θ::Array{Float64, 1}, pm::Int)
U = chain(n)
θ[1] = θ[1] + pm*(π/2)
append!(U, chain(n, put(n, loc=>chain(rand(rng,randG)(θ[loc]))) for loc = 1:n))
for j = 1:n-1
append!(U, chain(n, put(n, (j,j+1)=>rot(ZZ, β[j]))))
end
return U
end
function get_gradients(pmax::Int, spacing::Float64, n::Int, eps::Float64, O::PutBlock)
fp = trunc(log2(pmax))
times = union(trunc.([2^i for i in 1:spacing:fp]))
ψ1 = Yao.uniform_state(n)
ψ2 = Yao.uniform_state(n)
β = (π*0.5)*(2.0*rand(n-1) .- 1.0)
θ = (2*π*eps)*rand(n)
grads = zeros(length(times))
count = 0
ψ1 |> cgrad_flayer(n, β, eps, θ, 1)
ψ2 |> cgrad_flayer(n, β, eps, θ, -1)
for t in 1:last(times)
U = circuit_layer(n, β, eps)
ψ1 |> U
ψ2 |> U
if (t in times) == true
count = count + 1
grads[count] = real(expect(O, ψ1)) - real(expect(O, ψ2))
end
end
grads
end
Here I’m only computing the gradient with respect to the first parameter of the circuit. The code seems to work but it is way slower than the same code but for the entropy instead. I would really appreciate any advice/suggestion you can provide me.