diff --git a/docs/src/circuits.md b/docs/src/circuits.md index e4aa13f..ccd9bab 100644 --- a/docs/src/circuits.md +++ b/docs/src/circuits.md @@ -12,6 +12,9 @@ BraketSimulator.Circuit BraketSimulator.Operator BraketSimulator.QuantumOperator BraketSimulator.FreeParameter +BraketSimulator.Reset +BraketSimulator.Barrier +BraketSimulator.Delay BraketSimulator.Measure BraketSimulator.Instruction BraketSimulator.QubitSet diff --git a/src/Quasar.jl b/src/Quasar.jl index 8219c3e..11493f5 100644 --- a/src/Quasar.jl +++ b/src/Quasar.jl @@ -1,7 +1,7 @@ module Quasar using ..BraketSimulator -using Automa, AbstractTrees, DataStructures +using Automa, AbstractTrees, DataStructures, Dates using DataStructures: Stack using BraketSimulator: Control, Instruction, Result, bind_value!, remap, qubit_count, Circuit @@ -71,9 +71,7 @@ const qasm_tokens = [ :arrow_token => re"->", :reset_token => re"reset", :delay_token => re"delay", - :stretch_token => re"stretch", - :barrier_token => re"barrier", - :duration_token => re"duration", + :barrier_token => re"barrier", :void => re"void", :const_token => re"const", :assignment => re"=|-=|\+=|\*=|/=|^=|&=|\|=|<<=|>>=", @@ -110,12 +108,18 @@ const qasm_tokens = [ :string_token => '"' * rep(re"[ !#-~]" | re"\\\\\"") * '"' | '\'' * rep(re"[ -&(-~]" | ('\\' * re"[ -~]")) * '\'', :newline => re"\r?\n", :spaces => re"[\t ]+", - :durationof_token => re"durationof", # this MUST be lower than duration_token to preempt duration - :classical_type => re"bool|uint|int|float|angle|complex|array|bit", - :duration_value => (float | integer) * re"ns|µs|us|ms|s", + :classical_type => re"bool|uint|int|float|angle|complex|array|bit|stretch|duration", + :durationof_token => re"durationof", # this MUST be lower than classical_type to preempt duration + :duration_literal => (float | integer) * re"dt|ns|us|ms|s|\xce\xbc\x73", # transcode'd μs :forbidden_keyword => re"cal|defcal|extern", ] +const dt_type = Ref{DataType}() + +function __init__() + dt_type[] = Nanosecond +end + @eval @enum Token error $(first.(qasm_tokens)...) make_tokenizer((error, [Token(i) => j for (i,j) in enumerate(last.(qasm_tokens))] @@ -369,6 +373,15 @@ function parse_classical_type(tokens, stack, start, qasm) first(array_tokens)[end] == comma && popfirst!(array_tokens) size = parse_expression(array_tokens, stack, start, qasm) return QasmExpression(:classical_type, SizedArray(eltype, size)) + elseif var_type == "duration" + @warn "duration expression encountered -- currently `duration` is a no-op" + # TODO: add proper parsing of duration expressions, including + # support for units and algebraic durations like 2*a. + return QasmExpression(:classical_type, :duration) + elseif var_type == "stretch" + @warn "stretch expression encountered -- currently `stretch` is a no-op" + # TODO: add proper parsing of stretch expressions + return QasmExpression(:classical_type, :stretch) else !any(triplet->triplet[end] == semicolon, tokens) && push!(tokens, (-1, Int32(-1), semicolon)) size = is_sized ? parse_expression(tokens, stack, start, qasm) : QasmExpression(:integer_literal, -1) @@ -427,6 +440,21 @@ parse_oct_literal(token, qasm) = QasmExpression(:integer_literal, tryparse(I parse_bin_literal(token, qasm) = QasmExpression(:integer_literal, tryparse(Int, qasm[token[1]:token[1]+token[2]-1])) parse_float_literal(token, qasm) = QasmExpression(:float_literal, tryparse(Float64, qasm[token[1]:token[1]+token[2]-1])) parse_boolean_literal(token, qasm) = QasmExpression(:boolean_literal, tryparse(Bool, qasm[token[1]:token[1]+token[2]-1])) +function parse_duration_literal(token, qasm) + str = String(codeunits(qasm)[token[1]:token[1]+token[2]-1]) + duration = if endswith(str, "ns") + Nanosecond(tryparse(Int, chop(str, tail=2))) + elseif endswith(str, "ms") + Millisecond(tryparse(Int, chop(str, tail=2))) + elseif endswith(str, "us") || endswith(str, "μs") + Microsecond(tryparse(Int, chop(str, tail=2))) + elseif endswith(str, "s") + Second(tryparse(Int, chop(str, tail=1))) + elseif endswith(str, "dt") + dt_type[](tryparse(Int, chop(str, tail=2))) + end + QasmExpression(:duration_literal, duration) +end function parse_irrational_literal(token, qasm) raw_string = String(codeunits(qasm)[token[1]:token[1]+token[2]-1]) raw_string == "pi" && return QasmExpression(:irrational_literal, π) @@ -463,7 +491,7 @@ function extract_braced_block(tokens::Vector{Tuple{Int64, Int32, Token}}, stack, next_token[end] == rbracket && (closers_met += 1) push!(braced_tokens, next_token) end - pop!(braced_tokens) # closing } + pop!(braced_tokens) # closing ] push!(braced_tokens, (-1, Int32(-1), semicolon)) return braced_tokens end @@ -511,6 +539,7 @@ function parse_list_expression(tokens::Vector{Tuple{Int64, Int32, Token}}, stack end function parse_literal(tokens::Vector{Tuple{Int64, Int32, Token}}, stack, start, qasm) + tokens[1][end] == duration_literal && return parse_duration_literal(popfirst!(tokens), qasm) tokens[1][end] == string_token && return parse_string_literal(popfirst!(tokens), qasm) tokens[1][end] == hex && return parse_hex_literal(popfirst!(tokens), qasm) tokens[1][end] == oct && return parse_oct_literal(popfirst!(tokens), qasm) @@ -634,7 +663,7 @@ function parse_expression(tokens::Vector{Tuple{Int64, Int32, Token}}, stack, sta token_name = parse_bracketed_expression(pushfirst!(tokens, start_token), stack, start, qasm) elseif start_token[end] == classical_type token_name = parse_classical_type(pushfirst!(tokens, start_token), stack, start, qasm) - elseif start_token[end] ∈ (string_token, integer_token, float_token, hex, oct, bin, irrational, dot, boolean) + elseif start_token[end] ∈ (string_token, integer_token, float_token, hex, oct, bin, irrational, dot, boolean, duration_literal) token_name = parse_literal(pushfirst!(tokens, start_token), stack, start, qasm) elseif start_token[end] ∈ (mutable, readonly, const_token) token_name = parse_identifier(start_token, qasm) @@ -644,7 +673,6 @@ function parse_expression(tokens::Vector{Tuple{Int64, Int32, Token}}, stack, sta token_name = QasmExpression(:n_dims, QasmExpression(:integer_literal, parse(Int, dim))) end head(token_name) == :empty && throw(QasmParseError("unable to parse line with start token $(start_token[end])", stack, start, qasm)) - next_token = first(tokens) if next_token[end] == semicolon || next_token[end] == comma || start_token[end] ∈ (lbracket, lbrace) expr = token_name @@ -657,7 +685,7 @@ function parse_expression(tokens::Vector{Tuple{Int64, Int32, Token}}, stack, sta unary_op_symbol ∈ (:~, :!, :-) || throw(QasmParseError("invalid unary operator $unary_op_symbol.", stack, start, qasm)) next_expr = parse_expression(tokens, stack, start, qasm) # apply unary op to next_expr - if head(next_expr) ∈ (:identifier, :indexed_identifier, :integer_literal, :float_literal, :string_literal, :irrational_literal, :boolean_literal, :complex_literal, :function_call, :cast) + if head(next_expr) ∈ (:identifier, :indexed_identifier, :integer_literal, :float_literal, :string_literal, :irrational_literal, :boolean_literal, :complex_literal, :function_call, :cast, :duration_literal) expr = QasmExpression(:unary_op, unary_op_symbol, next_expr) elseif head(next_expr) == :binary_op # replace first argument @@ -1005,7 +1033,7 @@ function parse_qasm(clean_tokens::Vector{Tuple{Int64, Int32, Token}}, qasm::Stri line_exprs = collect(Iterators.reverse(line_body))[2:end] push!(stack, QasmExpression(:return, line_exprs)) elseif token == box - @warn "box expression encountered -- currently boxed and delayed expressions are not supported" + @warn "box expression encountered -- currently `box` is a no-op" box_expr = QasmExpression(:box) parse_block_body(box_expr, clean_tokens, stack, start, qasm) push!(stack, box_expr) @@ -1013,28 +1041,29 @@ function parse_qasm(clean_tokens::Vector{Tuple{Int64, Int32, Token}}, qasm::Stri @warn "reset expression encountered -- currently `reset` is a no-op" eol = findfirst(triplet->triplet[end] == semicolon, clean_tokens) reset_tokens = splice!(clean_tokens, 1:eol) - targets = parse_expression(reset_tokens, stack, start, qasm) + targets = parse_list_expression(reset_tokens, stack, start, qasm) push!(stack, QasmExpression(:reset, targets)) elseif token == barrier_token @warn "barrier expression encountered -- currently `barrier` is a no-op" eol = findfirst(triplet->triplet[end] == semicolon, clean_tokens) barrier_tokens = splice!(clean_tokens, 1:eol) - targets = parse_expression(barrier_tokens, stack, start, qasm) + targets = parse_list_expression(barrier_tokens, stack, start, qasm) push!(stack, QasmExpression(:barrier, targets)) - elseif token == duration_token - @warn "duration expression encountered -- currently `duration` is a no-op" - eol = findfirst(triplet->triplet[end] == semicolon, clean_tokens) - duration_tokens = splice!(clean_tokens, 1:eol) - # TODO: add proper parsing of duration expressions, including - # support for units and algebraic durations like 2*a. - #dur_expr = parse_expression(duration_tokens, stack, start, qasm) - push!(stack, QasmExpression(:duration)) - elseif token == stretch_token - @warn "stretch expression encountered -- currently `stretch` is a no-op" + elseif token == delay_token + @warn "delay expression encountered -- currently `delay` is a no-op" eol = findfirst(triplet->triplet[end] == semicolon, clean_tokens) - stretch_tokens = splice!(clean_tokens, 1:eol) - stretch_expr = parse_expression(stretch_tokens, stack, start, qasm) - push!(stack, QasmExpression(:stretch, stretch_expr)) + delay_tokens = splice!(clean_tokens, 1:eol) + delay_expr = QasmExpression(:delay) + # format is delay[duration]; or delay[duration] targets; + delay_duration = extract_braced_block(delay_tokens, stack, start, qasm) + push!(delay_expr, QasmExpression(:duration, parse_expression(delay_duration, stack, start, qasm))) + target_expr = QasmExpression(:targets) + if first(delay_tokens)[end] != semicolon # targets present + targets = parse_list_expression(delay_tokens, stack, start, qasm) + push!(target_expr, targets) + end + push!(delay_expr, target_expr) + push!(stack, delay_expr) elseif token == end_token push!(stack, QasmExpression(:end)) elseif token == identifier || token == builtin_gate @@ -1327,7 +1356,7 @@ function evaluate(v::V, expr::QasmExpression) where {V<:AbstractVisitor} step::Int = evaluate(v, raw_step) stop::Int = evaluate(v, raw_stop) return StepRange(start, step, stop) - elseif head(expr) ∈ (:integer_literal, :float_literal, :string_literal, :complex_literal, :irrational_literal, :boolean_literal) + elseif head(expr) ∈ (:integer_literal, :float_literal, :string_literal, :complex_literal, :irrational_literal, :boolean_literal, :duration_literal) return expr.args[1] elseif head(expr) == :array_literal return [evaluate(v, arg) for arg in convert(Vector{QasmExpression}, expr.args)] @@ -1630,8 +1659,21 @@ function (v::AbstractVisitor)(program_expr::QasmExpression) elseif head(program_expr) == :version return v elseif head(program_expr) == :reset + targets = program_expr.args[1]::QasmExpression + target_qubits = evaluate(v, targets) + push!(v, [BraketSimulator.Instruction(BraketSimulator.Reset(), t) for t in target_qubits]) return v elseif head(program_expr) == :barrier + targets = program_expr.args[1]::QasmExpression + target_qubits = evaluate(v, targets) + push!(v, [BraketSimulator.Instruction(BraketSimulator.Barrier(), t) for t in target_qubits]) + return v + elseif head(program_expr) == :delay + duration_expr = program_expr.args[1].args[1]::QasmExpression + targets = program_expr.args[2].args[1]::QasmExpression + target_qubits = evaluate(v, targets) + duration = evaluate(v, duration_expr) + push!(v, [BraketSimulator.Instruction(BraketSimulator.Delay(duration), t) for t in target_qubits]) return v elseif head(program_expr) == :stretch return v diff --git a/src/dm_simulator.jl b/src/dm_simulator.jl index dbcaf19..35763b9 100644 --- a/src/dm_simulator.jl +++ b/src/dm_simulator.jl @@ -148,11 +148,15 @@ function _evolve_op!( ) where {T<:Complex,S<:AbstractDensityMatrix{T},N<:Noise} apply_noise!(op, dms.density_matrix, target...) end -# Measure operators are no-ops for now as measurement is handled at the end -# of simulation, in the results computation step. If/when mid-circuit -# measurement is supported, this operation will collapse the density -# matrix on the measured qubits. +# Measure, barrier, reset, and delay operators are no-ops for now as +# measurement is handled at the end of simulation, in the results +# computation step. If/when mid-circuit # measurement is supported, +# this operation will collapse the density # matrix on the measured qubits. +# Barrier, reset, and delay are also to-do implementations. _evolve_op!(dms::DensityMatrixSimulator{T,S}, m::Measure, args...) where {T<:Complex,S<:AbstractDensityMatrix{T}} = return +_evolve_op!(dms::DensityMatrixSimulator{T,S}, b::Barrier, args...) where {T<:Complex,S<:AbstractDensityMatrix{T}} = return +_evolve_op!(dms::DensityMatrixSimulator{T,S}, r::Reset, args...) where {T<:Complex,S<:AbstractDensityMatrix{T}} = return +_evolve_op!(dms::DensityMatrixSimulator{T,S}, d::Delay, args...) where {T<:Complex,S<:AbstractDensityMatrix{T}} = return """ evolve!(dms::DensityMatrixSimulator{T, S<:AbstractMatrix{T}}, operations::Vector{Instruction}) -> DensityMatrixSimulator{T, S} diff --git a/src/gate_kernels.jl b/src/gate_kernels.jl index 36cd64d..7bd86a6 100644 --- a/src/gate_kernels.jl +++ b/src/gate_kernels.jl @@ -282,6 +282,9 @@ apply_gate!(::Val{false}, g::I, state_vec::AbstractStateVector{T}, qubits::Int.. apply_gate!(::Val{true}, g::I, state_vec::AbstractStateVector{T}, qubits::Int...) where {T<:Complex} = return apply_gate!(::Measure, state_vec, args...) = return +apply_gate!(::Reset, state_vec, args...) = return +apply_gate!(::Barrier, state_vec, args...) = return +apply_gate!(::Delay, state_vec, args...) = return function apply_gate!( g_matrix::Union{SMatrix{2,2,T}, Diagonal{T,SVector{2,T}}}, diff --git a/src/gates.jl b/src/gates.jl index 024ac71..bd86c17 100644 --- a/src/gates.jl +++ b/src/gates.jl @@ -115,9 +115,6 @@ qubit_count(g::Unitary) = convert(Int, log2(size(g.matrix, 1))) Parametrizable(g::AngledGate) = Parametrized() Parametrizable(g::Gate) = NonParametrized() parameters(g::AngledGate) = collect(filter(a->a isa FreeParameter, angles(g))) -parameters(g::Gate) = FreeParameter[] -bind_value!(g::G, params::Dict{Symbol, <:Real}) where {G<:Gate} = bind_value!(Parametrizable(g), g, params) -bind_value!(::NonParametrized, g::G, params::Dict{Symbol, <:Real}) where {G<:Gate} = g # nosemgrep function bind_value!(::Parametrized, g::G, params::Dict{Symbol, <:Real}) where {G<:AngledGate} new_angles = map(angles(g)) do angle diff --git a/src/noises.jl b/src/noises.jl index 46258fe..1d5a75b 100644 --- a/src/noises.jl +++ b/src/noises.jl @@ -141,11 +141,9 @@ end Base.:(==)(c1::MultiQubitPauliChannel{N}, c2::MultiQubitPauliChannel{M}) where {N,M} = N == M && c1.probabilities == c2.probabilities Parametrizable(g::Noise) = NonParametrized() -parameters(g::Noise) = parameters(Parametrizable(g), g) +parameters(g::Noise) = parameters(Parametrizable(g), g) parameters(::Parametrized, g::N) where {N<:Noise} = filter(x->x isa FreeParameter, [getproperty(g, fn) for fn in fieldnames(N)]) parameters(::NonParametrized, g::Noise) = FreeParameter[] -bind_value!(n::N, params::Dict{Symbol, <:Real}) where {N<:Noise} = bind_value!(Parametrizable(n), n, params) -bind_value!(::NonParametrized, n::N, params::Dict{Symbol, <:Real}) where {N<:Noise} = n # nosemgrep function bind_value!(::Parametrized, g::N, params::Dict{Symbol, <:Real}) where {N<:Noise} diff --git a/src/operators.jl b/src/operators.jl index 456b4ab..72157bb 100644 --- a/src/operators.jl +++ b/src/operators.jl @@ -54,6 +54,8 @@ 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 @@ -66,3 +68,47 @@ Measure() = Measure(-1) Parametrizable(m::Measure) = NonParametrized() qubit_count(::Type{Measure}) = 1 qubit_count(m::Measure) = qubit_count(Measure) + +""" + Reset(index) <: QuantumOperator + +Represents an active reset operation on targeted qubit, stored in the classical register at `index`. +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) + +""" + Barrier(index) <: QuantumOperator + +Represents a barrier operation on targeted qubit, stored in the classical register at `index`. +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) + +""" + Delay(index, duration::Time) <: QuantumOperator + +Represents a delay operation for `duration` on targeted qubit, +stored in the classical register at `index`. +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) diff --git a/src/schemas.jl b/src/schemas.jl index a582a18..ee60dfb 100644 --- a/src/schemas.jl +++ b/src/schemas.jl @@ -22,4 +22,6 @@ end Instruction(o::O, target) where {O<:Operator} = Instruction{O}(o, QubitSet(target...)) Base.:(==)(ix1::Instruction{O}, ix2::Instruction{O}) where {O<:Operator} = (ix1.operator == ix2.operator && ix1.target == ix2.target) bind_value!(ix::Instruction{O}, param_values::Dict{Symbol, <:Real}) where {O<:Operator} = Instruction{O}(bind_value!(ix.operator, param_values), ix.target) +bind_value!(o::O, params::Dict{Symbol, <:Real}) where {O<:Operator} = bind_value!(Parametrizable(o), o, params) +bind_value!(::NonParametrized, o::O, params::Dict{Symbol, <:Real}) where {O<:Operator} = o remap(@nospecialize(ix::Instruction{O}), mapping::Dict{<:Integer, <:Integer}) where {O} = Instruction{O}(copy(ix.operator), [mapping[q] for q in ix.target]) diff --git a/test/test_openqasm3.jl b/test/test_openqasm3.jl index 3472873..0df44d6 100644 --- a/test/test_openqasm3.jl +++ b/test/test_openqasm3.jl @@ -1,4 +1,4 @@ -using BraketSimulator.Quasar, Statistics, LinearAlgebra, BraketSimulator, BraketSimulator.Observables +using BraketSimulator.Quasar, BraketSimulator.Dates, Statistics, LinearAlgebra, BraketSimulator, BraketSimulator.Observables get_tol(shots::Int) = return ( shots > 0 ? Dict("atol" => 0.1, "rtol" => 0.15) : Dict("atol" => 0.01, "rtol" => 0) @@ -557,13 +557,57 @@ get_tol(shots::Int) = return ( """ @test_throws Quasar.QasmParseError parse_qasm(qasm) end + @testset "Delay $duration" for (duration, ix) in (("200us", Microsecond(200)), + ("100μs", Microsecond(100)), + ("50ns", Nanosecond(50)), + ("20dt", Nanosecond(20)), + ("10ms", Millisecond(10)), + ("1s", Second(1)), + ) + + + qasm = """ + qubit[4] q; + x q[0]; + delay[$duration] q[0], q[1]; + """ + @test_warn "delay expression encountered -- currently `delay` is a no-op" parse_qasm(qasm) + circuit = Quasar.to_circuit(qasm) + @test circuit.instructions == [BraketSimulator.Instruction(BraketSimulator.X(), 0), + BraketSimulator.Instruction(BraketSimulator.Delay(ix), 0), + BraketSimulator.Instruction(BraketSimulator.Delay(ix), 1), + ] + simulation = BraketSimulator.StateVectorSimulator(4, 0) + ref_circ = BraketSimulator.Circuit() + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.X(), 0)) + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.I(), 1)) + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.I(), 2)) + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.I(), 3)) + ref_sim = BraketSimulator.StateVectorSimulator(4, 0) + BraketSimulator.evolve!(simulation, circuit.instructions) + BraketSimulator.evolve!(ref_sim, ref_circ.instructions) + @test simulation.state_vector ≈ ref_sim.state_vector + end @testset "Barrier" begin qasm = """ qubit[4] q; x q[0]; barrier q[0]; + #pragma braket result state_vector """ @test_warn "barrier expression encountered -- currently `barrier` is a no-op" parse_qasm(qasm) + circuit = Quasar.to_circuit(qasm) + @test circuit.instructions == [BraketSimulator.Instruction(BraketSimulator.X(), 0), BraketSimulator.Instruction(BraketSimulator.Barrier(), 0)] + simulation = BraketSimulator.StateVectorSimulator(4, 0) + ref_circ = BraketSimulator.Circuit() + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.X(), 0)) + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.I(), 1)) + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.I(), 2)) + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.I(), 3)) + ref_sim = BraketSimulator.StateVectorSimulator(4, 0) + BraketSimulator.evolve!(simulation, circuit.instructions) + BraketSimulator.evolve!(ref_sim, ref_circ.instructions) + @test simulation.state_vector ≈ ref_sim.state_vector end @testset "Stretch" begin qasm = """ @@ -584,6 +628,18 @@ get_tol(shots::Int) = return ( reset q[0]; """ @test_warn "reset expression encountered -- currently `reset` is a no-op" parse_qasm(qasm) + circuit = Quasar.to_circuit(qasm) + @test circuit.instructions == [BraketSimulator.Instruction(BraketSimulator.X(), 0), BraketSimulator.Instruction(BraketSimulator.Reset(), 0)] + simulation = BraketSimulator.StateVectorSimulator(4, 0) + ref_circ = BraketSimulator.Circuit() + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.X(), 0)) + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.I(), 1)) + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.I(), 2)) + push!(ref_circ.instructions, BraketSimulator.Instruction(BraketSimulator.I(), 3)) + ref_sim = BraketSimulator.StateVectorSimulator(4, 0) + BraketSimulator.evolve!(simulation, circuit.instructions) + BraketSimulator.evolve!(ref_sim, ref_circ.instructions) + @test simulation.state_vector ≈ ref_sim.state_vector end @testset "Gate call missing/extra args" begin qasm = """ diff --git a/test/test_operators.jl b/test/test_operators.jl new file mode 100644 index 0000000..83fb79c --- /dev/null +++ b/test/test_operators.jl @@ -0,0 +1,12 @@ +using BraketSimulator, BraketSimulator.Dates, Test + +@testset "Operators" begin + for op in (BraketSimulator.Measure(), + BraketSimulator.Reset(), + BraketSimulator.Barrier(), + BraketSimulator.Delay(Microsecond(200)) + ) + @test BraketSimulator.qubit_count(op) == 1 + @test BraketSimulator.parameters(op) == BraketSimulator.FreeParameter[] + end +end