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

feature: Add Reset, Barrier, Delay, and bump deps #104

Merged
merged 5 commits into from
Oct 7, 2024
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,5 +170,5 @@ jobs:
run: |
using Documenter: DocMeta, doctest
using Braket
DocMeta.setdocmeta!(Braket, :DocTestSetup, :(using Braket); recursive=true)
DocMeta.setdocmeta!(Braket, :DocTestSetup, :(using Braket, Braket.Dates); recursive=true)
doctest(Braket)
10 changes: 5 additions & 5 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Braket"
uuid = "19504a0f-b47d-4348-9127-acc6cc69ef67"
authors = ["Katharine Hyatt <[email protected]>"]
version = "0.9.4"
version = "0.9.5"

[deps]
AWS = "fbe9abb3-538b-5e4e-ba9e-bc94f4f92ebc"
Expand Down Expand Up @@ -33,7 +33,7 @@ Tar = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[compat]
AWS = "=1.91.0"
AWS = "=1.92.0"
AWSS3 = "=0.11.2"
Aqua = "=0.8"
AxisArrays = "=0.4.7"
Expand All @@ -50,20 +50,20 @@ Downloads = "1"
Graphs = "=1.11.2"
HTTP = "=1.10.8"
InteractiveUtils = "1.6"
JLD2 = "=0.4.51"
JLD2 = "=0.5.4"
JSON3 = "=1.14.0"
LinearAlgebra = "1.6"
Logging = "1.6"
Markdown = "=0.7.5"
Mocking = "=0.7.9"
Mocking = "=0.8.1"
NamedTupleTools = "=0.14.3"
OrderedCollections = "=1.6.3"
Pkg = "1.6"
Random = "1.6"
SparseArrays = "1.6"
StaticArrays = "=1.9.7"
Statistics = "1.6"
StructTypes = "=1.10.0"
StructTypes = "=1.11.0"
Tar = "1.9.3"
Test = "1.6"
UUIDs = "1.6"
Expand Down
6 changes: 3 additions & 3 deletions PyBraket/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "PyBraket"
uuid = "e85266a6-1825-490b-a80e-9b9469c53660"
authors = ["Katharine Hyatt <[email protected]>"]
version = "0.9.4"
version = "0.9.5"

[deps]
Braket = "19504a0f-b47d-4348-9127-acc6cc69ef67"
Expand All @@ -14,13 +14,13 @@ StructTypes = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"

[compat]
Aqua = "=0.8"
Braket = "=0.9.4"
Braket = "=0.9.5"
CondaPkg = "=0.2.23"
DataStructures = "=0.18.20"
LinearAlgebra = "1.6"
PythonCall = "=0.9.22"
Statistics = "1"
StructTypes = "=1.10.0"
StructTypes = "=1.11.0"
Test = "1.6"
julia = "1.6"

Expand Down
2 changes: 1 addition & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
push!(LOAD_PATH,"../src/")

using Documenter, Braket
using Documenter, Braket, Braket.Dates

makedocs(sitename="Braket.jl")

Expand Down
6 changes: 6 additions & 0 deletions docs/src/circuits.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ qubits
qubit_count
measure
Measure
barrier
Barrier
reset(::Circuit, ::Any)
Reset
delay
Delay
```

## Output to IR
Expand Down
2 changes: 1 addition & 1 deletion src/Braket.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export provider_name, properties, type
export apply_gate_noise!, apply
export logs, log_metric, metrics, @hybrid_job
export depth, qubit_count, qubits, ir, IRType, OpenQASMSerializationProperties
export OpenQasmProgram, Measure, measure
export OpenQasmProgram, Measure, Reset, Barrier, Delay, measure, reset, barrier, delay
export simulate
export QueueDepthInfo, QueueType, Normal, Priority, queue_depth, queue_position

Expand Down
65 changes: 65 additions & 0 deletions src/circuit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,71 @@ function measure(c::Circuit, target_qubits)
return _add_measure!(c, target_qubits)
end

"""
reset(c::Circuit, target_qubits) -> Circuit

Add a [`Reset`](@ref) operator to `c`, performing an active reset to the `|0>` state on the targeted qubits.
A `Reset` operation can be applied after a [`Measure`](@ref) to re-initialize the qubit and allow it to be reused
after mid-circuit measurement.

# Examples
```jldoctest
julia> circ = Circuit([(H, 0), (CNot, 0, 1)]);

julia> circ = reset(circ, 0);

julia> circ.instructions
3-element Vector{Braket.Instruction}:
Braket.Instruction{H}(H(), QubitSet(0))
Braket.Instruction{CNot}(CNot(), QubitSet(0, 1))
Braket.Instruction{Reset}(Reset(), QubitSet(0))
```
"""
Base.reset(c::Circuit, target_qubits) = (foreach(t->add_instruction!(c, Instruction(Reset(), t)), target_qubits); return c)

"""
delay(c::Circuit, duration::Dates.Period, target_qubits) -> Circuit

Add a [`Delay`](@ref) operator to `c`, which forces all targeted qubits to wait for `duration`
before any new operations may be applied to any of them.

# Examples
```jldoctest
julia> circ = Circuit([(H, 0), (CNot, 0, 1)]);

julia> circ = delay(circ, Nanosecond(10), [0, 1]);

julia> circ.instructions
3-element Vector{Braket.Instruction}:
Braket.Instruction{H}(H(), QubitSet(0))
Braket.Instruction{CNot}(CNot(), QubitSet(0, 1))
Braket.Instruction{Delay}(Delay(Nanosecond(10)), QubitSet(0, 1))
```
"""
delay(c::Circuit, duration::Dates.Period, target_qubits) = (add_instruction!(c, Instruction(Delay(duration), target_qubits)); return c)
# TODO enforce this in `Moments` as well

"""
barrier(c::Circuit, target_qubits) -> Circuit

Add a [`Barrier`](@ref) operator to `c`, which forces all targeted qubits to reach the barrier before any new
operations may be applied to any of them.

# Examples
```jldoctest
julia> circ = Circuit([(H, 0), (CNot, 0, 1)]);

julia> circ = barrier(circ, [0, 1]);

julia> circ.instructions
3-element Vector{Braket.Instruction}:
Braket.Instruction{H}(H(), QubitSet(0))
Braket.Instruction{CNot}(CNot(), QubitSet(0, 1))
Braket.Instruction{Barrier}(Barrier(), QubitSet(0, 1))
```
"""
barrier(c::Circuit, target_qubits) = (add_instruction!(c, Instruction(Barrier(), target_qubits)); return c)

function openqasm_header(c::Circuit, sps::SerializationProperties=OpenQASMSerializationProperties())
ir_instructions = ["OPENQASM 3.0;"]
for p in sort(string.(c.parameters))
Expand Down
56 changes: 52 additions & 4 deletions src/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@ struct PauliEigenvalues{N}
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.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
Expand Down Expand Up @@ -71,8 +69,9 @@ end
Measure() = Measure(-1)
Parametrizable(m::Measure) = NonParametrized()
chars(::Type{Measure}) = ("M",)
chars(m::Measure) = ("M",)
chars(::Measure) = chars(Measure)
qubit_count(::Type{Measure}) = 1
qubit_count(::Measure) = qubit_count(Measure)
ir(m::Measure, target::QubitSet, ::Val{:JAQCD}; kwargs...) = error("measure instructions are not supported with JAQCD.")
function ir(m::Measure, target::QubitSet, ::Val{:OpenQASM}; serialization_properties=OpenQASMSerializationProperties())
instructions = Vector{String}(undef, length(target))
Expand All @@ -83,3 +82,52 @@ function ir(m::Measure, target::QubitSet, ::Val{:OpenQASM}; serialization_proper
end
return join(instructions, "\n")
end

"""
Reset() <: QuantumOperator

Represents an active reset operation on targeted qubit.
"""
struct Reset <: QuantumOperator end
Parametrizable(m::Reset) = NonParametrized()
chars(::Type{Reset}) = ("Reset",)
chars(::Reset) = chars(Reset)
label(::Reset) = "reset"
qubit_count(::Type{Reset}) = 1
qubit_count(r::Reset) = qubit_count(Reset)

"""
Barrier() <: QuantumOperator

Represents a barrier operation on targeted qubit.
"""
struct Barrier <: QuantumOperator end
Parametrizable(b::Barrier) = NonParametrized()
chars(::Type{Barrier}) = ("Barrier",)
chars(r::Barrier) = chars(Barrier)
label(::Barrier) = "barrier"
qubit_count(::Type{Barrier}) = 1
qubit_count(b::Barrier) = qubit_count(Barrier)

"""
Delay(duration::Period) <: QuantumOperator

Represents a delay operation for `duration` on targeted qubit.
"""
struct Delay <: QuantumOperator
duration::Dates.Period
end
Parametrizable(m::Delay) = NonParametrized()
chars(d::Delay) = ("Delay($(label(d.duration)))",)
label(d::Delay) = "delay[$(label(d.duration))]"
qubit_count(::Type{Delay}) = 1
qubit_count(d::Delay) = qubit_count(Delay)
Base.:(==)(d1::Delay, d2::Delay) = d1.duration == d2.duration
label(d::Microsecond) = "$(d.value)ms"
label(d::Nanosecond) = "$(d.value)ns"
label(d::Second) = "$(d.value)s"

ir(ix::Union{Reset, Barrier, Delay}, target::QubitSet, ::Val{:JAQCD}; kwargs...) = error("$(label(ix)) instructions are not supported with JAQCD.")
function ir(ix::Union{Reset, Barrier, Delay}, target::QubitSet, v::Val{:OpenQASM}; serialization_properties=OpenQASMSerializationProperties())
return join(("$(label(ix)) $(format_qubits(qubit, serialization_properties));" for qubit in target), "\n")
end
53 changes: 53 additions & 0 deletions test/circuit_timing.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using Braket, Braket.Dates, Test
using Braket: Instruction, VIRTUAL, PHYSICAL, OpenQASMSerializationProperties

@testset "Barrier, reset, and delay operators" begin
@test Barrier() isa Braket.QuantumOperator
@test Reset() isa Braket.QuantumOperator
@test Braket.Parametrizable(Reset()) == Braket.NonParametrized()
@test Braket.Parametrizable(Barrier()) == Braket.NonParametrized()
@test Braket.Parametrizable(Delay(Microsecond(200))) == Braket.NonParametrized()
@test qubit_count(Reset()) == 1
@test qubit_count(Barrier()) == 1
circ = Circuit([(H, 0), (CNot, 0, 1)])
circ = barrier(circ, 0)
@test circ.instructions == [Instruction{H}(H(), QubitSet(0)), Instruction{CNot}(CNot(), QubitSet(0, 1)), Instruction{Barrier}(Barrier(), QubitSet(0))]
circ = Circuit([(H, 0), (CNot, 0, 1)])
circ = reset(circ, 0)
@test circ.instructions == [Instruction{H}(H(), QubitSet(0)), Instruction{CNot}(CNot(), QubitSet(0, 1)), Instruction{Reset}(Reset(), QubitSet(0))]
circ = Circuit([(H, 0), (CNot, 0, 1)])
circ = delay(circ, Nanosecond(10), 0)
@test circ.instructions == [Instruction{H}(H(), QubitSet(0)), Instruction{CNot}(CNot(), QubitSet(0, 1)), Instruction{Delay}(Delay(Nanosecond(10)), QubitSet(0))]
@test qubit_count(Delay(Microsecond(200))) == 1
@test Delay(Microsecond(200)) isa Braket.QuantumOperator
@testset "Equality" for t in (Barrier, Reset)
t1 = t()
t2 = t()
non_t = Measure()
@test t1 == t2
@test t1 != non_t
end
@test Delay(Nanosecond(10)) != Delay(Microsecond(10))
@test Delay(Nanosecond(10_000)) == Delay(Microsecond(10))
@test Braket.chars(Barrier()) == ("Barrier",)
@test Braket.chars(Reset()) == ("Reset",)
@test Braket.chars(Delay(Nanosecond(4))) == ("Delay(4ns)",)
@test Braket.chars(Delay(Microsecond(4))) == ("Delay(4ms)",)
@testset "To IR" for (t, str) in ((Barrier(), "barrier"),
(Reset(), "reset"),
(Delay(Second(1)), "delay[1s]"),
)
@testset "Invalid ir_type $ir_type" for (ir_type, message) in ((:JAQCD, "$str instructions are not supported with JAQCD."),
)
@test_throws ErrorException(message) ir(t, QubitSet([0]), Val(ir_type))
end
@testset "OpenQASM, target $target, serialization properties $sps" for (target, sps, expected_ir) in (
([0], OpenQASMSerializationProperties(qubit_reference_type=VIRTUAL), "$str q[0];"),
([4], OpenQASMSerializationProperties(qubit_reference_type=PHYSICAL), "$str \$4;"),
)


@test ir(Instruction(t, target), Val(:OpenQASM); serialization_properties=sps) == expected_ir
end
end
end
5 changes: 5 additions & 0 deletions test/measure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ using Braket: Instruction, VIRTUAL, PHYSICAL, OpenQASMSerializationProperties

@testset "Measure operator" begin
@test Measure() isa Braket.QuantumOperator
@test Braket.Parametrizable(Measure()) == Braket.NonParametrized()
@test qubit_count(Measure()) == 1
@testset "Equality" begin
measure1 = Measure()
measure2 = Measure()
Expand All @@ -11,6 +13,9 @@ using Braket: Instruction, VIRTUAL, PHYSICAL, OpenQASMSerializationProperties
@test measure1 != non_measure
end
@test Braket.chars(Measure()) == ("M",)
circ = Circuit([(H, 0), (CNot, 0, 1)])
circ = measure(circ, 0)
@test circ.instructions == [Instruction{H}(H(), QubitSet(0)), Instruction{CNot}(CNot(), QubitSet(0, 1)), Instruction{Measure}(Measure(0), QubitSet(0))]

@testset "To IR" begin
@testset "Invalid ir_type $ir_type" for (ir_type, message) in ((:JAQCD, "measure instructions are not supported with JAQCD."),
Expand Down
4 changes: 4 additions & 0 deletions test/observables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ using LinearAlgebra: eigvals
Braket.IRType[] = :JAQCD
@testset "pauli eigenvalues" begin
z = [1.0 0.0; 0.0 -1.0]
@test PauliEigenvalues(Val(1))[1] == 1.0
@test PauliEigenvalues(Val(1))[2] == -1.0
@test collect(PauliEigenvalues(Val(1))) == [1.0, -1.0]
for n in 2:6
pe = PauliEigenvalues(Val(n))
@test length(pe) == 2^n
mat = kron(ntuple(i->diag(z), n)...)
for ix in 1:2^n
@test pe[ix] == mat[ix]
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ for group in groups
include("device.jl")
include("circuits.jl")
include("measure.jl")
include("circuit_timing.jl")
include("free_parameter.jl")
include("gates.jl")
include("observables.jl")
Expand Down
Loading