Skip to content
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

Adding YaoBraketExt as a weak dependency #464

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
130 changes: 130 additions & 0 deletions ext/YaoBraketExt.jl
Original file line number Diff line number Diff line change
@@ -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
12 changes: 12 additions & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +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"
YaoAPI = "0843a435-28de-4971-9e8b-a9641b2983a8"
YaoArrayRegister = "e600142f-9330-5003-8abb-0ebd767abc51"
YaoBlocks = "418bc28f-b43b-5e0b-a6e7-61bbc1a2c1df"
YaoSym = "3b27209a-d3d6-11e9-3c0f-41eb92b2cb9d"
36 changes: 36 additions & 0 deletions test/braket.jl
Original file line number Diff line number Diff line change
@@ -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
4 changes: 4 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down