Skip to content
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
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
lcov.info
*.profraw
*.json
/Manifest.toml
/docs/Manifest.toml
Manifest.toml
/docs/build/
/.coverage
.CondaPkg/
.DS_Store
*/.DS_Store
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.7"
authors = ["Katharine Hyatt <hyatkath@amazon.com> and contributors", "Amazon Web Services"]
version = "0.0.8"

[deps]
Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa"
Expand All @@ -27,7 +27,7 @@ BraketSimulatorBraketExt = "Braket"

[compat]
Aqua = "=0.8"
Braket = "0.9.5"
Braket = "0.10"
Combinatorics = "=1.0.2"
DataStructures = "=0.18.20"
Dates = "1.6"
Expand Down
19 changes: 2 additions & 17 deletions ext/BraketSimulatorBraketExt/BraketSimulatorBraketExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ end
Braket.name(d::BraketSimulator.AbstractSimulator) = BraketSimulator.name(d)
Braket.properties(d::BraketSimulator.AbstractSimulator) = BraketSimulator.properties(d)
Braket.simulate(d::BraketSimulator.AbstractSimulator, program::Braket.OpenQasmProgram, args...; kwargs...) = convert(Braket.GateModelTaskResult, BraketSimulator.simulate(d, convert(BraketSimulator.OpenQasmProgram, program), args...; kwargs...))
Braket.simulate(d::BraketSimulator.AbstractSimulator, program::Braket.Program, qubit_count::Int, shots::Int; kwargs...) = convert(Braket.GateModelTaskResult, BraketSimulator.simulate(d, convert(BraketSimulator.Program, program), shots; kwargs...))

Base.convert(::Type{Braket.TaskMetadata}, tm::BraketSimulator.TaskMetadata) = Braket.TaskMetadata(Braket.braketSchemaHeader("braket.task_result.task_metadata", "1"), tm.id, tm.shots, tm.deviceId, tm.deviceParameters, tm.createdAt, tm.endedAt, tm.status, tm.failureReason)
Base.convert(::Type{Braket.AdditionalMetadata}, am::BraketSimulator.AdditionalMetadata) = Braket.AdditionalMetadata(convert(Braket.AbstractProgram, am.action), nothing, nothing, nothing, nothing, nothing, nothing, nothing, nothing)
Expand All @@ -26,6 +25,7 @@ function Base.convert(::Type{Braket.GateModelTaskResult}, r::BraketSimulator.Gat
r.measurementProbabilities,
rts,
r.measuredQubits,
r.outputs,
task_meta,
addl_meta)
end
Expand Down Expand Up @@ -142,22 +142,7 @@ Base.convert(::Type{Braket.Instruction}, ix::BraketSimulator.Instruction) = Brak

Base.convert(::Type{BraketSimulator.OpenQasmProgram}, p::Braket.OpenQasmProgram) = BraketSimulator.OpenQasmProgram(BraketSimulator.braketSchemaHeader("braket.ir.openqasm.program", "1"), p.source, p.inputs)

# have to handle the special case of 2-qubit Hermitians carefully due to endianness
# nosemgrep
function Base.convert(::Type{BraketSimulator.Program}, p::Braket.Program)
ixs = [convert(BraketSimulator.Instruction, ix) for ix in p.instructions]
rts = [convert(BraketSimulator.AbstractProgramResult, rt) for rt in p.results]
bris = map(p.basis_rotation_instructions) do bri
if bri.operator isa Unitary && length(bri.target) == 2
return BraketSimulator.Instruction(BraketSimulator.Unitary(BraketSimulator.fix_endianness(bri.operator.matrix)), bri.target)
else
return convert(BraketSimulator.Instruction, bri)
end
end
p = BraketSimulator.Program(BraketSimulator.braketSchemaHeader("braket.ir.jaqcd.program", "1"), ixs, rts, bris)
return p
end
Base.convert(::Type{Braket.AbstractProgram}, p::BraketSimulator.Program) = Braket.Program(Braket.braketSchemaHeader("braket.ir.jaqcd.program", "1"), [convert(Braket.Instruction, ix) for ix in p.instructions],[convert(Braket.AbstractProgramResult, rt) for rt in p.results], [convert(Braket.Instruction, ix) for ix in p.basis_rotation_instructions])
Base.convert(::Type{Braket.AbstractProgram}, p::BraketSimulator.Program) = Braket.OpenQasmProgram(Braket.braketSchemaHeader("braket.ir.openqasm.program", "1"), "", nothing)
Base.convert(::Type{Braket.AbstractProgram}, p::BraketSimulator.OpenQasmProgram) = Braket.OpenQasmProgram(Braket.braketSchemaHeader("braket.ir.openqasm.program", "1"), p.source, p.inputs)

function __init__()
Expand Down
46 changes: 25 additions & 21 deletions src/BraketSimulator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ function _bundle_results(
nothing,
results,
sorted_qubits,
nothing,
_build_metadata(simulator, circuit_ir)...
)
end
Expand Down Expand Up @@ -198,10 +199,10 @@ function _get_measured_qubits(program, qubit_count::Int)
return measured_qubits
end
"""
_prepare_program(circuit_ir::OpenQasmProgram, inputs::Dict{String, <:Any}, shots::Int) -> (Program, Int)
_prepare_program(circuit_ir::OpenQasmProgram, inputs::Dict{String, <:Any}, shots::Int) -> (Circuit, Int)

Parse the OpenQASM3 source, apply any `inputs` provided for the simulation, and compute
basis rotation instructions if running with non-zero shots. Return the `Program` after
basis rotation instructions if running with non-zero shots. Return the `Circuit` after
parsing and the qubit count of the circuit.
"""
function _prepare_program(circuit_ir::OpenQasmProgram, inputs::Dict{String, <:Any}, shots::Int)
Expand Down Expand Up @@ -234,7 +235,7 @@ function _prepare_program(circuit_ir::Program, inputs::Dict{String, <:Any}, shot
return bound_program, qubit_count(circuit_ir)
end
"""
_combine_operations(program, shots::Int) -> Program
_combine_operations(program, shots::Int) -> Vector{Instruction}

Combine explicit instructions and basis rotation instructions (if necessary).
Validate that all operations are performed on qubits within `qubit_count`.
Expand All @@ -248,14 +249,17 @@ function _combine_operations(program, shots::Int)
return operations
end
"""
_compute_results(::, simulator, program::Program, n_qubits::Int, shots::Int) -> Vector{ResultTypeValue}
_compute_results(simulator, program, n_qubits::Int, shots::Int) -> Vector{ResultTypeValue}

Compute the results once `simulator` has finished applying all the instructions. The results depend on the IR type if `shots>0`:
Compute the results once `simulator` has finished applying all the instructions. The
behavior depends on the IR shape and on shot count:

- For JAQCD IR (`Program`), the results array is *empty* because the Braket SDK computes the results from the IR directly.
- For OpenQASM IR (`OpenQasmProgram`), the results array is *empty* only if no results are present in the parsed IR. Otherwise,
the results array is populated with the parsed result types (to help the Braket SDK compute them from the sampled measurements)
and a placeholder zero value.
- For Julia-side `Program` IR, the results array is *empty* when `shots > 0` because the
Braket SDK will compute results from the IR directly; for `shots == 0` the results are
computed analytically from the simulator state.
- For `OpenQasmProgram` IR (which is parsed into a `Circuit`), the results array is empty
only if no results are present; otherwise it is populated with the parsed result types
(and a placeholder zero value if shots > 0) so the SDK can compute them from samples.
"""
function _compute_results(simulator, program::Circuit, n_qubits, shots)
results = program.result_types
Expand All @@ -278,14 +282,14 @@ function _compute_results(simulator, program::Program, n_qubits, shots)
end
end
function _validate_circuit_ir(simulator, circuit_ir::Program, qubit_count::Int, shots::Int)
_validate_ir_results_compatibility(simulator, circuit_ir.results, Val(:JAQCD))
_validate_ir_instructions_compatibility(simulator, circuit_ir, Val(:JAQCD))
_validate_ir_results_compatibility(simulator, circuit_ir.results, Val(:OpenQASM))
_validate_ir_instructions_compatibility(simulator, circuit_ir, Val(:OpenQASM))
_validate_shots_and_ir_results(shots, circuit_ir.results, qubit_count)
return
end
function _validate_circuit_ir(simulator, circuit_ir::Circuit, qubit_count::Int, shots::Int)
_validate_ir_results_compatibility(simulator, circuit_ir.result_types, Val(:JAQCD))
_validate_ir_instructions_compatibility(simulator, circuit_ir, Val(:JAQCD))
_validate_ir_results_compatibility(simulator, circuit_ir.result_types, Val(:OpenQASM))
_validate_ir_instructions_compatibility(simulator, circuit_ir, Val(:OpenQASM))
_validate_shots_and_ir_results(shots, circuit_ir.result_types, qubit_count)
return
end
Expand All @@ -294,11 +298,11 @@ end
simulate(simulator::AbstractSimulator, circuit_ir::Union{OpenQasmProgram, Program}, shots::Int; kwargs...) -> GateModelTaskResult

Simulate the evolution of a state vector or density matrix using the passed-in `simulator`.
The instructions to apply (gates and noise channels) and measurements to make are
encoded in `circuit_ir`. Supported IR formats are `OpenQASMProgram` (OpenQASM3)
and `Program` (JAQCD). Returns a `GateModelTaskResult` containing the individual shot
measurements (if `shots > 0`), final calculated results, circuit IR, and metadata
about the task.
The instructions to apply (gates and noise channels) and measurements to make are encoded in
`circuit_ir`. Supported IR formats are `OpenQasmProgram` (OpenQASM3 source string) and the
Julia-side `Program` container (typically built via `Program(c::Circuit)`).
Returns a `GateModelTaskResult` containing the individual shot measurements (if `shots > 0`),
final calculated results, circuit IR, and metadata about the task.
"""
function simulate(
simulator::AbstractSimulator,
Expand All @@ -321,9 +325,9 @@ end
simulate(simulator::AbstractSimulator, circuit_irs::Vector{<:Union{Program, OpenQasmProgram}}, shots::Int; max_parallel::Int=min(32, Threads.nthreads()), inputs=Dict{String,Float64}(), kwargs...) -> Vector{GateModelTaskResult}

Simulate the evolution of a *batch* of state vectors or density matrices using the passed in `simulator`.
The instructions to apply (gates and noise channels) and measurements to make are
encoded in `circuit_irs`. Supported IR formats are `OpenQASMProgram` (OpenQASM3)
and `Program` (JAQCD).
The instructions to apply (gates and noise channels) and measurements to make are encoded in
`circuit_irs`. Supported IR formats are `OpenQasmProgram` (OpenQASM3 source string) and the
Julia-side `Program` container.

The simulation of the batch is done in parallel using threads.
The keyword argument `max_parallel` specifies the number of evolutions to simulate in
Expand Down
2 changes: 1 addition & 1 deletion src/circuit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ qubit_count(p::Program) = length(qubits(p))

function Base.convert(::Type{Program}, c::Circuit) # nosemgrep
lowered_rts = map(StructTypes.lower, c.result_types)
header = braketSchemaHeader("braket.ir.jaqcd.program" ,"1")
header = braketSchemaHeader("braket.ir.openqasm.program", "1")
return Program(header, c.instructions, lowered_rts, c.basis_rotation_instructions)
end
Program(c::Circuit) = convert(Program, c)
Expand Down
2 changes: 0 additions & 2 deletions src/dm_simulator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,8 @@ Query the properties and capabilities of a `DensityMatrixSimulator`, including w
"""
properties(d::DensityMatrixSimulator) = dm_props
supported_operations(d::DensityMatrixSimulator, ::Val{:OpenQASM}) = dm_props.action["braket.ir.openqasm.program"].supportedOperations
supported_operations(d::DensityMatrixSimulator, ::Val{:JAQCD}) = dm_props.action["braket.ir.jaqcd.program"].supportedOperations
supported_operations(d::DensityMatrixSimulator) = supported_operations(d::DensityMatrixSimulator, Val(:OpenQASM))
supported_result_types(d::DensityMatrixSimulator, ::Val{:OpenQASM}) = dm_props.action["braket.ir.openqasm.program"].supportedResultTypes
supported_result_types(d::DensityMatrixSimulator, ::Val{:JAQCD}) = dm_props.action["braket.ir.jaqcd.program"].supportedResultTypes
supported_result_types(d::DensityMatrixSimulator) = supported_result_types(d::DensityMatrixSimulator, Val(:OpenQASM))
device_id(dms::DensityMatrixSimulator) = "braket_dm_v2"
name(dms::DensityMatrixSimulator) = "DensityMatrixSimulator"
Expand Down
145 changes: 0 additions & 145 deletions src/properties.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,77 +17,6 @@ const sv_props_dict = Dict(
:shotsRange => [0, sv_max_shots],
),
:action => Dict(
"braket.ir.jaqcd.program" => Dict(
:actionType => "braket.ir.jaqcd.program",
:version => ["1"],
:supportedOperations => [
"ccnot",
"cnot",
"cphaseshift",
"cphaseshift00",
"cphaseshift01",
"cphaseshift10",
"cswap",
"cv",
"cy",
"cz",
"ecr",
"h",
"i",
"iswap",
"pswap",
"phaseshift",
"prx",
"rx",
"ry",
"rz",
"s",
"si",
"swap",
"t",
"ti",
"unitary",
"v",
"vi",
"x",
"xx",
"xy",
"y",
"yy",
"z",
"zz",
],
:supportedResultTypes => [
Dict(
:name => "Sample",
:observables => sv_observables,
:minShots => 1,
:maxShots => sv_max_shots,
),
Dict(
:name => "Expectation",
:observables => sv_observables,
:minShots => 0,
:maxShots => sv_max_shots,
),
Dict(
:name => "Variance",
:observables => sv_observables,
:minShots => 0,
:maxShots => sv_max_shots,
),
Dict(
:name => "Adjoint_Gradient",
:observables => sv_observables,
:minShots => 0,
:maxShots => 0,
),
Dict(:name => "Probability", :minShots => 0, :maxShots => sv_max_shots),
Dict(:name => "StateVector", :minShots => 0, :maxShots => 0),
Dict(:name => "DensityMatrix", :minShots => 0, :maxShots => 0),
Dict(:name => "Amplitude", :minShots => 0, :maxShots => 0),
],
),
"braket.ir.openqasm.program" => Dict(
:actionType => "braket.ir.openqasm.program",
:version => ["1"],
Expand Down Expand Up @@ -336,80 +265,6 @@ const dm_props_dict = Dict(
:supportsUnassignedMeasurements => true,
:disabledQubitRewiringSupported => false,
),
"braket.ir.jaqcd.program" => Dict(
:actionType => "braket.ir.jaqcd.program",
:version => ["1"],
:supportedOperations => [
"amplitude_damping",
"bit_flip",
"ccnot",
"cnot",
"cphaseshift",
"cphaseshift00",
"cphaseshift01",
"cphaseshift10",
"cswap",
"cv",
"cy",
"cz",
"depolarizing",
"ecr",
"generalized_amplitude_damping",
"h",
"i",
"iswap",
"kraus",
"pauli_channel",
"two_qubit_pauli_channel",
"phase_flip",
"phase_damping",
"phaseshift",
"pswap",
"prx",
"rx",
"ry",
"rz",
"s",
"si",
"swap",
"t",
"ti",
"two_qubit_dephasing",
"two_qubit_depolarizing",
"unitary",
"v",
"vi",
"x",
"xx",
"xy",
"y",
"yy",
"z",
"zz",
],
:supportedResultTypes => [
Dict(
:name => "Sample",
:observables => dm_observables,
:minShots => 1,
:maxShots => dm_max_shots,
),
Dict(
:name => "Expectation",
:observables => dm_observables,
:minShots => 0,
:maxShots => dm_max_shots,
),
Dict(
:name => "Variance",
:observables => dm_observables,
:minShots => 0,
:maxShots => dm_max_shots,
),
Dict(:name => "Probability", :minShots => 0, :maxShots => dm_max_shots),
Dict(:name => "DensityMatrix", :minShots => 0, :maxShots => 0),
],
),
),
:paradigm => Dict(:qubitCount => dm_qubit_count),
:deviceParameters =>
Expand Down
Loading
Loading