Flux Integration

Qaintellect.jl integrates the various utilities of Qaintessent.jl into Flux.jl. This allows the creation of trainable layers, which can integrated into ML or optimization algorithms.

Example

This example shows test code that uses the Flux.gradient() call to calculate the gradients of the Circuit object.

using Flux
using Qaintessent
using Qaintellect
using LinearAlgebra

# construct parametrized circuit
N = 4
rz = RzGate(1.5π)
ps = PhaseShiftGate(0.3)
ry = RyGate(√2)
n = randn(Float64, 3)
n /= norm(n)
rg = RotationGate(0.2π, n)
cgc = [
    circuit_gate(3, HadamardGate()),
    circuit_gate(2, rz, (1, 4)),
    circuit_gate(2, 3, SwapGate()),
    circuit_gate(3, ps),
    circuit_gate(3, rg),
    circuit_gate(1, ry),
]

# measurement operators
meas = [MeasurementOperator(Matrix{Float64}(I, 2^N, 2^N), Tuple(1:N)), MeasurementOperator(Hermitian(randn(ComplexF64, 2^N, 2^N)), Tuple(1:N))]
c = Circuit{N}(cgc, meas)

# input quantum state
ψ = randn(ComplexF64, 2^N)

# fictitious gradients of cost function with respect to output quantum state after applying circuit gates
Δ = 0.1*randn(ComplexF64, 2^N)

# Flux will call pullback function with argument Δ
grads = Flux.gradient(() -> real(dot(Δ, apply(c.moments, ψ))), Flux.Params([rz.θ, ps.ϕ, ry.θ, rg.nθ]))

# arguments used implicitly via references
# ngradient calculates gradients via finite difference, adapted from https://github.com/FluxML/Zygote.jl/blob/master/test/gradcheck.jl 
f(args...) = real(dot(Δ, apply(c.moments, ψ)))
all(isapprox.(ngradient(f, rz.θ, ps.ϕ, ry.θ, rg.nθ),
    (grads[rz.θ], grads[ps.ϕ], grads[ry.θ], grads[rg.nθ]), rtol=1e-5, atol=1e-5))

# output
true