diff --git a/Project.toml b/Project.toml index f95d974d..2d7576d3 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Braket" uuid = "19504a0f-b47d-4348-9127-acc6cc69ef67" authors = ["Katharine Hyatt "] -version = "0.9.4" +version = "0.9.5" [deps] AWS = "fbe9abb3-538b-5e4e-ba9e-bc94f4f92ebc" @@ -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" @@ -50,12 +50,12 @@ 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" @@ -63,7 +63,7 @@ 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" diff --git a/PyBraket/Project.toml b/PyBraket/Project.toml index df115738..0aafbf02 100644 --- a/PyBraket/Project.toml +++ b/PyBraket/Project.toml @@ -1,7 +1,7 @@ name = "PyBraket" uuid = "e85266a6-1825-490b-a80e-9b9469c53660" authors = ["Katharine Hyatt "] -version = "0.9.4" +version = "0.9.5" [deps] Braket = "19504a0f-b47d-4348-9127-acc6cc69ef67" @@ -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" diff --git a/docs/src/circuits.md b/docs/src/circuits.md index 79d7719a..f0ed6f1a 100644 --- a/docs/src/circuits.md +++ b/docs/src/circuits.md @@ -44,6 +44,12 @@ qubits qubit_count measure Measure +barrier +Barrier +Braket.reset +Reset +delay +Delay ``` ## Output to IR diff --git a/src/Braket.jl b/src/Braket.jl index ec4b5206..0ee1ef4b 100644 --- a/src/Braket.jl +++ b/src/Braket.jl @@ -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 diff --git a/src/circuit.jl b/src/circuit.jl index 2b363d09..c15b4ff5 100644 --- a/src/circuit.jl +++ b/src/circuit.jl @@ -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) + +""" + 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)) +# 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)) + function openqasm_header(c::Circuit, sps::SerializationProperties=OpenQASMSerializationProperties()) ir_instructions = ["OPENQASM 3.0;"] for p in sort(string.(c.parameters)) diff --git a/src/operators.jl b/src/operators.jl index a1d93c51..cceec94a 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -83,3 +83,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(r::Reset) = ("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) = ("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 diff --git a/test/circuit_timing.jl b/test/circuit_timing.jl new file mode 100644 index 00000000..b405c858 --- /dev/null +++ b/test/circuit_timing.jl @@ -0,0 +1,38 @@ +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 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)",) + + @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 diff --git a/test/runtests.jl b/test/runtests.jl index 91807f74..d3ccfc90 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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")