From 9258f3174a66dac50b5eb25df5455eef41685d8e Mon Sep 17 00:00:00 2001 From: Ruihao Li <47152529+ruihao-li@users.noreply.github.com> Date: Mon, 27 Mar 2023 23:38:08 -0400 Subject: [PATCH 1/2] Add YaoBraketExt and test --- Project.toml | 18 +++--- ext/YaoBraketExt.jl | 130 ++++++++++++++++++++++++++++++++++++++++++++ test/Project.toml | 6 ++ test/braket.jl | 36 ++++++++++++ test/runtests.jl | 4 ++ 5 files changed, 183 insertions(+), 11 deletions(-) create mode 100644 ext/YaoBraketExt.jl create mode 100644 test/Project.toml create mode 100644 test/braket.jl diff --git a/Project.toml b/Project.toml index 82cf3ec8..fa372b75 100644 --- a/Project.toml +++ b/Project.toml @@ -12,6 +12,12 @@ YaoArrayRegister = "e600142f-9330-5003-8abb-0ebd767abc51" YaoBlocks = "418bc28f-b43b-5e0b-a6e7-61bbc1a2c1df" YaoSym = "3b27209a-d3d6-11e9-3c0f-41eb92b2cb9d" +[weakdeps] +Braket = "19504a0f-b47d-4348-9127-acc6cc69ef67" + +[extensions] +YaoBraketExt = "Braket" + [compat] BitBasis = "0.8" LuxurySparse = "0.7" @@ -20,14 +26,4 @@ YaoAPI = "0.4" YaoArrayRegister = "0.9" YaoBlocks = "0.13" YaoSym = "0.6" -julia = "1" - -[extras] -Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -SymEngine = "123dc426-2d89-5057-bbad-38513e3affd8" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[targets] -test = ["Test", "LinearAlgebra", "Documenter", "Random", "SymEngine"] +julia = "1" \ No newline at end of file diff --git a/ext/YaoBraketExt.jl b/ext/YaoBraketExt.jl new file mode 100644 index 00000000..72718fa6 --- /dev/null +++ b/ext/YaoBraketExt.jl @@ -0,0 +1,130 @@ +module YaoBraketExt + +export generate_inst, convert_to_braket + +using YaoBlocks +using Braket + +""" + convert_to_braket(qc) + +Convert an `AbstractBlock` in Yao to a `Circuit` in Braket. + +- `qc`: An `AbstractBlock` (typically a `ChainBlock`), i.e., circuit that is to be converted. +""" +function convert_to_braket(qc::AbstractBlock{N}) where {N} + inst = generate_inst(qc) + return Circuit(inst) +end + +""" + generate_inst(qc) + +Parses the YaoIR into a list of Braket supported instructions. + +- `qc`: An `AbstractBlock` (typically a `ChainBlock`), i.e., circuit that is to be run. +""" +function generate_inst(qc::AbstractBlock{N}) where {N} + inst = [] + generate_inst!(inst, basicstyle(qc), [0:N...], Int[]) + return inst +end + +function generate_inst!(inst, qc_simpl::ChainBlock, locs, controls) + for block in subblocks(qc_simpl) + generate_inst!(inst, block, locs, controls) + end +end + +function generate_inst!(inst, blk::PutBlock{N,M}, locs, controls) where {N,M} + generate_inst!(inst, blk.content, sublocs(blk.locs, locs), controls) +end + +function generate_inst!(inst, blk::ControlBlock{N,GT,C}, locs, controls) where {N,GT,C} + any(==(0), blk.ctrl_config) && error("Inverse Control used in Control gate context.") + generate_inst!( + inst, + blk.content, + sublocs(blk.locs, locs), + [controls..., sublocs(blk.ctrl_locs, locs)...], + ) +end + +function generate_inst!(inst, m::YaoBlocks.Measure{N}, locs, controls) where {N} + mlocs = sublocs(m.locations isa AllLocs ? [1:N...] : [m.locations...], locs) + (m.operator isa ComputationalBasis) || + error("Measuring an operator is not yet supported.") + (length(controls) == 0) || error("Controlled measure is not yet supported.") + push!(inst, (Braket.Probability, mlocs)) +end + +# General unitary gates +function generate_inst!( + inst, + gate::GeneralMatrixBlock{N,C,MT}, + locs, + controls, +) where {N,C,MT} + (length(controls) == 0) || + error("Controlled version of general unitary is not yet supported.") + push!(inst, (Braket.Unitary, [locs...], gate.mat)) +end + +# Primitive cosntant gates +for (GT, BKG, MAXC) in [ + (:XGate, Braket.X, 2), + (:YGate, Braket.Y, 1), + (:ZGate, Braket.Z, 1), + (:I2Gate, Braket.I, 0), + (:HGate, Braket.H, 0), + (:TGate, Braket.T, 0), + (:SWAPGate, Braket.Swap, 1), +] + @eval function generate_inst!(inst, gate::$GT, locs, controls) + if length(controls) <= $MAXC + if length(controls) == 0 + braket_gate = $BKG + elseif length(controls) == 1 + braket_gate = ( + typeof(gate) == YaoBlocks.XGate ? Braket.CNot : + typeof(gate) == YaoBlocks.YGate ? Braket.CY : + typeof(gate) == YaoBlocks.ZGate ? Braket.CZ : Braket.CSwap + ) + else + braket_gate = Braket.CCNot + end + push!(inst, (braket_gate, [controls..., locs...])) + else + error("Too many control bits!") + end + end +end + +# Rotation gates +for (GT, BKG, PARAMS, MAXC) in [ + (:(RotationGate{2,T,XGate} where {T}), Braket.Rx, :(b.theta), 0), + (:(RotationGate{2,T,YGate} where {T}), Braket.Ry, :(b.theta), 0), + (:(RotationGate{2,T,ZGate} where {T}), Braket.Rz, :(b.theta), 0), + (:(ShiftGate), Braket.PhaseShift, :(b.theta), 1), +] + @eval function generate_inst!(inst, b::$GT, locs, controls) + if length(controls) <= $MAXC + if length(controls) == 0 + braket_gate = $BKG + else + braket_gate = Braket.CPhaseShift + end + push!(inst, (braket_gate, [controls..., locs...], $PARAMS)) + else + error("Too many control bits! Got $controls (length > $($(MAXC)))") + end + end +end + +sublocs(subs, locs) = [locs[i] for i in subs] + +function basicstyle(blk::AbstractBlock) + YaoBlocks.Optimise.simplify(blk, rules = [YaoBlocks.Optimise.to_basictypes]) +end + +end \ No newline at end of file diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 00000000..9bec983e --- /dev/null +++ b/test/Project.toml @@ -0,0 +1,6 @@ +[deps] +Braket = "19504a0f-b47d-4348-9127-acc6cc69ef67" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +SymEngine = "123dc426-2d89-5057-bbad-38513e3affd8" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" \ No newline at end of file diff --git a/test/braket.jl b/test/braket.jl new file mode 100644 index 00000000..c695b629 --- /dev/null +++ b/test/braket.jl @@ -0,0 +1,36 @@ +using YaoBlocks, Braket, YaoBraketExt +using Test + +@testset "YaoBlocksBraket.jl" begin + yao_qc = chain( + 3, + put(1 => YaoBlocks.X), + put(2 => YaoBlocks.Y), + put(3 => YaoBlocks.Z), + put(2 => YaoBlocks.T), + put(3 => YaoBlocks.Ry(0.7)), + put(1 => YaoBlocks.GeneralMatrixBlock([0.0+0.0im 1.0+0.0im; 1.0+0.0im 0.0+0.0im])), + swap(1, 2), + control(3, (1, 2) => YaoBlocks.SWAP), + control((2, 3), 1 => YaoBlocks.X), + control(3, 2 => YaoBlocks.Z), + YaoBlocks.Measure(3, locs = 1:2), + ) + braket_inst = [ + (Braket.X, [0]), + (Braket.Y, [1]), + (Braket.Z, [2]), + (Braket.T, [1]), + (Braket.Ry, [2], 0.7), + (Braket.Unitary, [0], [0.0+0.0im 1.0+0.0im; 1.0+0.0im 0.0+0.0im]), + (Braket.Swap, [0, 1]), + (Braket.CSwap, [2, 0, 1]), + (Braket.CCNot, [1, 2, 0]), + (Braket.CZ, [2, 1]), + (Braket.Probability, [0, 1]), + ] + @test generate_inst(yao_qc) == braket_inst + + braket_circ = Circuit(braket_inst) + @test convert_to_braket(yao_qc) == braket_circ +end diff --git a/test/runtests.jl b/test/runtests.jl index 0142031e..d76cb769 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -12,6 +12,10 @@ using Random include("easybuild/easybuild.jl") end +@testset "braket" begin + include("braket.jl") +end + DocMeta.setdocmeta!(Yao, :DocTestSetup, :(using Yao, YaoAPI, YaoArrayRegister, YaoBlocks, YaoSym, BitBasis); recursive=true) Documenter.doctest(YaoAPI; manual=false) From b05962c39fb80125ed709cb70a6ead395d7ec42e Mon Sep 17 00:00:00 2001 From: Ruihao Li <47152529+ruihao-li@users.noreply.github.com> Date: Tue, 28 Mar 2023 10:34:52 -0400 Subject: [PATCH 2/2] Fix `test/Project.toml` --- test/Project.toml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/Project.toml b/test/Project.toml index 9bec983e..0e85e32e 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,6 +1,12 @@ [deps] +BitBasis = "50ba71b6-fa0f-514d-ae9a-0916efc90dcf" Braket = "19504a0f-b47d-4348-9127-acc6cc69ef67" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" SymEngine = "123dc426-2d89-5057-bbad-38513e3affd8" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" \ No newline at end of file +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +YaoAPI = "0843a435-28de-4971-9e8b-a9641b2983a8" +YaoArrayRegister = "e600142f-9330-5003-8abb-0ebd767abc51" +YaoBlocks = "418bc28f-b43b-5e0b-a6e7-61bbc1a2c1df" +YaoSym = "3b27209a-d3d6-11e9-3c0f-41eb92b2cb9d"