-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Calculating gradients with cureg #56
Comments
Hi, If your operation contains only rotation block, a simple patch should make it work. (Or decompose your circuits to rotation gates) e.g. the variational circuit in
This is because we forbid scalar access to CuArrays in CuYao to prevent incorrect access. We will add this patch in CuYao later. For non-rotation block, a lot extra work is required to work around the share write issue on GPU. |
@GiggleLiu Thank you, Leo! This worked well for rotation gates. For the generic case, in principle one can use a decomposition into cnots + rotations. There is a problem however when rotations shall have same angle -- |
Good point. Note: FYI:Zygote is a quite flexible AD framework, but requires some try and error. If you have any problem using it feel free to ping me in this issue or in Julia slack, Here is a project that combines Yao and neural networks, |
I guess the @GiggleLiu 's point is not to replace |
Sure, I am not suggesting using the backward rules generated by Zygote, but gluing the backward rules in Yao with Zygote. BTW: mutating arrays are not properly supported in Zygote yet, so it will throw an error if you don't import the patch file in the example. |
Thanks @GiggleLiu @wangleiphy I joined Slack channels, so will be learning AD, and look into beta-VQE. |
I have got GPU backprop to work for gates of the form """
HEVGate <: PrimitiveBlock{2}
$(FIELDS)
Time evolution with the Heisenberg interaction gate.
"""
mutable struct HEVGate{T<:Real} <: YaoBlocks.PrimitiveBlock{2}
theta::T
end
function Yao.mat(::Type{T}, gate::HEVGate) where {T<:Real}
return Complex{T}[exp(-1im*gate.theta) 0 0 0;
0 exp(1im*gate.theta)*cos(2gate.theta) -1im*exp(1im*gate.theta)*sin(2gate.theta) 0;
0 -1im*exp(1im*gate.theta)*sin(2gate.theta) exp(1im*gate.theta)*cos(2gate.theta) 0;
0 0 0 exp(-1im*gate.theta)]
end
function Yao.mat(::Type{T}, gate::HEVGate) where {T<:Complex}
return T[exp(-1im*gate.theta) 0 0 0;
0 exp(1im*gate.theta)*cos(2gate.theta) -1im*exp(1im*gate.theta)*sin(2gate.theta) 0;
0 -1im*exp(1im*gate.theta)*sin(2gate.theta) exp(1im*gate.theta)*cos(2gate.theta) 0;
0 0 0 exp(-1im*gate.theta)]
end
@const_gate HEVGenerator::ComplexF64 = [1 0 0 0; 0 -1 2 0; 0 2 -1 0; 0 0 0 1]
@const_gate HEVGenerator::ComplexF32
Base.show(io::IO, block::HEVGate{T}) where {T} = print(io, "$(HEVGate){$T}($(block.theta))")
YaoBase.niparams(::HEVGate) = 1
YaoBase.getiparams(block::HEVGate) = block.theta
YaoBase.setiparams!(block::HEVGate, param::Real) = (block.theta = param; block)
Base.adjoint(block::HEVGate) = HEVGate(-block.theta)
YaoBlocks.cache_key(block::HEVGate) = block.theta
YaoAPI.nqudits(::HEVGate) = 2
# Here comes the actual AD part.
function YaoBlocks.AD.backward_params!(st, block::PutBlock{D,<:Any, HEVGate{T}}, collector) where {D,T}
out, outδ = st
in = copy(out)
ham = put(nqudits(block), block.locs => HEVGate)
g = state(in |> ham) ⋅ state(outδ)
pushfirst!(collector, -imag(g))
nothing
end
function YaoBlocks.AD.apply_back!(st, block::PutBlock{D,<:Any, HEVGate{T}}, collector) where {D,T}
out, outδ = st
adjblock = block'
YaoBlocks.AD.backward_params!((out, outδ), block, collector)
in = apply!(out, adjblock)
inδ = apply!(outδ, adjblock)
return (in, inδ)
end Maybe this helps getting AD to work more generally on GPUs? |
Thanks for the note! we recently have an efficient CUDA implementation of time evolution using Krylov to be open sourcing soon, we will integrate that implementation to solve this issue eventually. |
Thank you very much for the note! It is only a temporary solution, @Roger-luo 's implementation is definitely more trust-worthy. |
Not sure if it should an enhancement or fix, but I noticed that quantum backpropagation does not work with a GPU register (reg |> cu). It raises "scalar getindex is disallowed" warning. Is there a workaround? GPU operation for expect'(..) can speed up calculations by a lot.
The text was updated successfully, but these errors were encountered: