Skip to content

Commit

Permalink
change: Add translation and tests for Braket circuit timing ops (#57)
Browse files Browse the repository at this point in the history
  • Loading branch information
kshyatt-aws authored Oct 9, 2024
1 parent 9319fcd commit 2de28b3
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 54 deletions.
1 change: 1 addition & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
version:
- '1.9'
- '1.10'
- '1.11'
- 'nightly'
os:
- ubuntu-latest
Expand Down
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "BraketSimulator"
uuid = "76d27892-9a0b-406c-98e4-7c178e9b3dff"
authors = ["Katharine Hyatt <hyatkath@amazon.com> and contributors"]
version = "0.0.5"
version = "0.0.6"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Expand Down Expand Up @@ -30,7 +30,7 @@ BraketSimulatorBraketExt = "Braket"
AbstractTrees = "=0.4.5"
Aqua = "=0.8"
Automa = "=1.0.4"
Braket = "=0.9.4"
Braket = "0.9.5"
Combinatorics = "=1.0.2"
DataStructures = "=0.18.20"
Dates = "1.6"
Expand All @@ -45,7 +45,7 @@ PythonCall = "=0.9.23"
Random = "1.6"
StaticArrays = "1.9"
StatsBase = "0.34"
StructTypes = "=1.10.0"
StructTypes = "=1.11.0"
Test = "1.6"
UUIDs = "1.6"
julia = "1.9"
Expand Down
12 changes: 9 additions & 3 deletions ext/BraketSimulatorBraketExt/BraketSimulatorBraketExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ function Base.convert(::Type{Braket.GateModelTaskResult}, r::BraketSimulator.Gat
addl_meta)
end

Braket.qubit_count(o::O) where {O<:BraketSimulator.Operator} = BraketSimulator.qubit_count(o)
Braket.qubit_count(o::O) where {O<:BraketSimulator.Observables.Observable} = BraketSimulator.qubit_count(o)
Braket.qubit_count(::Type{O}) where {O<:BraketSimulator.Operator} = BraketSimulator.qubit_count(O)
Braket.qubit_count(o::O) where {O<:BraketSimulator.Operator} = BraketSimulator.qubit_count(o)
Braket.qubit_count(o::O) where {O<:BraketSimulator.Observables.Observable} = BraketSimulator.qubit_count(o)
Braket.qubit_count(::Type{O}) where {O<:BraketSimulator.Operator} = BraketSimulator.qubit_count(O)

for (braket_sim, simulator_sym) in ((:(Braket.X), :(BraketSimulator.X)),
(:(Braket.Y), :(BraketSimulator.Y)),
Expand Down Expand Up @@ -106,6 +106,12 @@ Base.convert(::Type{Braket.AbstractProgramResult}, rt::BraketSimulator.IR.Amplit
Base.convert(::Type{BraketSimulator.AbstractProgramResult}, rt::Braket.IR.Amplitude) = BraketSimulator.IR.Amplitude(rt.states, rt.type)
Base.convert(::Type{BraketSimulator.Operator}, m::Braket.Measure) = BraketSimulator.Measure(m.index)
Base.convert(::Type{Braket.Operator}, m::BraketSimulator.Measure) = Braket.Measure(m.index)
Base.convert(::Type{BraketSimulator.Operator}, ::Braket.Reset) = BraketSimulator.Reset()
Base.convert(::Type{Braket.Operator}, ::BraketSimulator.Reset) = Braket.Reset()
Base.convert(::Type{BraketSimulator.Operator}, ::Braket.Barrier) = BraketSimulator.Barrier()
Base.convert(::Type{Braket.Operator}, ::BraketSimulator.Barrier) = Braket.Barrier()
Base.convert(::Type{BraketSimulator.Operator}, d::Braket.Delay) = BraketSimulator.Delay(d.duration)
Base.convert(::Type{Braket.Operator}, d::BraketSimulator.Delay) = Braket.Delay(d.duration)

Base.convert(::Type{BraketSimulator.Operator}, g::Braket.MS) = BraketSimulator.MS(ntuple(i->convert(Union{FreeParameter, Real}, g.angle[i]), 3))
Base.convert(::Type{Braket.Operator}, g::BraketSimulator.MS) = Braket.MS(ntuple(i->convert(Union{Braket.FreeParameter, Real}, g.angle[i]), 3))
Expand Down
9 changes: 6 additions & 3 deletions src/BraketSimulator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,12 @@ function _prepare_program(circuit_ir::Program, inputs::Dict{String, <:Any}, shot
operations::Vector{Instruction} = circuit_ir.instructions
symbol_inputs = Dict(Symbol(k) => v for (k, v) in inputs)
operations = [bind_value!(operation, symbol_inputs) for operation in operations]
qc = qubit_count(circuit_ir)
bound_program = Program(circuit_ir.braketSchemaHeader, operations, circuit_ir.results, circuit_ir.basis_rotation_instructions)
return bound_program, qc
bound_program = Program(circuit_ir.braketSchemaHeader,
operations,
circuit_ir.results,
circuit_ir.basis_rotation_instructions,
)
return bound_program, qubit_count(circuit_ir)
end
"""
_combine_operations(program, shots::Int) -> Program
Expand Down
65 changes: 23 additions & 42 deletions src/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Subtypes include [`Gate`](@ref), [`Noise`](@ref), [`Observable`](@ref BraketSimu
"""
abstract type Operator end

abstract type Parametrizable end
struct Parametrized end
struct NonParametrized end

"""
QuantumOperator < Operator
Expand All @@ -15,28 +19,20 @@ Subtypes include [`Gate`](@ref) and [`Noise`](@ref).
abstract type QuantumOperator <: Operator end
StructTypes.StructType(::Type{QuantumOperator}) = StructTypes.AbstractType()
StructTypes.subtypes(::Type{QuantumOperator}) = (h=H, i=I, x=X, y=Y, z=Z, s=S, si=Si, t=T, ti=Ti, v=V, vi=Vi, cnot=CNot, swap=Swap, iswap=ISwap, cv=CV, cy=CY, cz=CZ, ecr=ECR, ccnot=CCNot, cswap=CSwap, unitary=Unitary, rx=Rx, ry=Ry, rz=Rz, phaseshift=PhaseShift, pswap=PSwap, xy=XY, cphaseshift=CPhaseShift, cphaseshift00=CPhaseShift00, cphaseshift01=CPhaseShift01, cphaseshift10=CPhaseShift10, xx=XX, yy=YY, zz=ZZ, gpi=GPi, gpi2=GPi2, ms=MS, prx=PRx, u=U, gphase=GPhase, kraus=Kraus, bit_flip=BitFlip, phase_flip=PhaseFlip, pauli_channel=PauliChannel, amplitude_damping=AmplitudeDamping, phase_damping=PhaseDamping, depolarizing=Depolarizing, two_qubit_dephasing=TwoQubitDephasing, two_qubit_depolarizing=TwoQubitDepolarizing, generalized_amplitude_damping=GeneralizedAmplitudeDamping, multi_qubit_pauli_channel=MultiQubitPauliChannel, measure=Measure, reset=Reset, barrier=Barrier, delay=Delay)


abstract type Parametrizable end
struct Parametrized end
struct NonParametrized end
parameters(::QuantumOperator) = FreeParameter[]

struct PauliEigenvalues{N}
coeff::Float64
PauliEigenvalues{N}(coeff::Float64=1.0) where {N} = new(coeff)
end
PauliEigenvalues(::Val{N}, coeff::Float64=1.0) where {N} = PauliEigenvalues{N}(coeff)
Base.length(p::PauliEigenvalues{N}) where {N} = 2^N
function Base.iterate(p::PauliEigenvalues{N}, ix::Int=1) where {N}
return ix <= length(p) ? (p[ix], ix+1) : nothing
end

Base.length(::PauliEigenvalues{N}) where {N} = 2^N
Base.iterate(p::PauliEigenvalues{N}, ix::Int=1) where {N} = ix <= length(p) ? (p[ix], ix+1) : nothing
Base.getindex(p::PauliEigenvalues{1}, i::Int)::Float64 = getindex((p.coeff, -p.coeff), i)
function Base.getindex(p::PauliEigenvalues{N}, i::Int)::Float64 where N
i_block = div(i-1, 2)
split = div(2^(N-1)-1, 2)
if N < 5
total_evs = 2^N
is_front = !isodd(mod(i-1, 2))
ev = is_front ? p.coeff : -p.coeff
mi = mod(i_block, 2)
Expand All @@ -57,8 +53,6 @@ function Base.getindex(p::PauliEigenvalues{N}, i::Int)::Float64 where N
end
Base.getindex(p::PauliEigenvalues{N}, ix::Vector{Int}) where {N} = [p[i] for i in ix]

parameters(o::QuantumOperator) = FreeParameter[]

"""
Measure(index) <: QuantumOperator
Expand All @@ -68,54 +62,41 @@ struct Measure <: QuantumOperator
index::Int
end
Measure() = Measure(-1)
Parametrizable(m::Measure) = NonParametrized()
qubit_count(::Type{Measure}) = 1
qubit_count(m::Measure) = qubit_count(Measure)
StructTypes.constructfrom(::Type{Measure}, nt) = Measure()

"""
Reset(index) <: QuantumOperator
Reset() <: QuantumOperator
Represents an active reset operation on targeted qubit, stored in the classical register at `index`.
Represents an active reset operation on targeted qubit.
For now, this is a no-op.
"""
struct Reset <: QuantumOperator
index::Int
end
Reset() = Reset(-1)
Parametrizable(m::Reset) = NonParametrized()
qubit_count(::Type{Reset}) = 1
qubit_count(m::Reset) = qubit_count(Reset)
struct Reset <: QuantumOperator end
StructTypes.constructfrom(::Type{Reset}, nt) = Reset()

"""
Barrier(index) <: QuantumOperator
Barrier() <: QuantumOperator
Represents a barrier operation on targeted qubit, stored in the classical register at `index`.
Represents a barrier operation on targeted qubit.
For now, this is a no-op.
"""
struct Barrier <: QuantumOperator
index::Int
end
Barrier() = Barrier(-1)
Parametrizable(m::Barrier) = NonParametrized()
qubit_count(::Type{Barrier}) = 1
qubit_count(m::Barrier) = qubit_count(Barrier)
struct Barrier <: QuantumOperator end
StructTypes.constructfrom(::Type{Barrier}, nt) = Barrier()

"""
Delay(index, duration::Time) <: QuantumOperator
Delay(duration::Time) <: QuantumOperator
Represents a delay operation for `duration` on targeted qubit,
stored in the classical register at `index`.
Represents a delay operation for `duration` on targeted qubit.
For now, this is a no-op.
"""
struct Delay <: QuantumOperator
index::Int
duration::Dates.Period
end
Delay(duration::Dates.Period) = Delay(-1, duration)
Parametrizable(m::Delay) = NonParametrized()
qubit_count(::Type{Delay}) = 1
qubit_count(m::Delay) = qubit_count(Delay)
StructTypes.constructfrom(::Type{Delay}, nt) = Delay(only(nt.arguments))

for T in (:Barrier, :Reset, :Delay, :Measure)
@eval begin
qubit_count(::Type{$T}) = 1
qubit_count(o::$T) = qubit_count($T)
Parametrizable(::$T) = NonParametrized()
end
end
3 changes: 3 additions & 0 deletions test/test_braket_integration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ end

@testset "Type conversions" begin
@test convert(Braket.Operator, convert(BraketSimulator.Operator, Braket.Measure(2))) == Braket.Measure(2)
@test convert(Braket.Operator, convert(BraketSimulator.Operator, Braket.Reset())) == Braket.Reset()
@test convert(Braket.Operator, convert(BraketSimulator.Operator, Braket.Barrier())) == Braket.Barrier()
@test convert(Braket.Operator, convert(BraketSimulator.Operator, Braket.Delay(Braket.Nanosecond(2)))) == Braket.Delay(Braket.Nanosecond(2))
angle1 = 0.2
angle2 = 0.1
angle3 = π
Expand Down
5 changes: 3 additions & 2 deletions test/test_operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ using BraketSimulator, BraketSimulator.Dates, Test
BraketSimulator.Barrier(),
BraketSimulator.Delay(Microsecond(200))
)
@test BraketSimulator.qubit_count(op) == 1
@test BraketSimulator.parameters(op) == BraketSimulator.FreeParameter[]
@test BraketSimulator.qubit_count(op) == 1
@test BraketSimulator.qubit_count(typeof(op)) == 1
@test BraketSimulator.parameters(op) == BraketSimulator.FreeParameter[]
end
end
2 changes: 1 addition & 1 deletion test/test_python_ext.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ using Test, JSON3, PythonCall, BraketSimulator
@test result.resultTypes[1].type.type == "expectation"
@test result.resultTypes[1].type.targets == [0]
@test result.resultTypes[1].type.observable == ["z"]
@test result.resultTypes[1].value == 0.0
@test abs(result.resultTypes[1].value) 0.0 atol=eps(result.resultTypes[1].value)

simple_bell_qasm = """
h \$0;
Expand Down

0 comments on commit 2de28b3

Please sign in to comment.