Internals
These functions are for internal use for preparing IRs for simulation and validating properties to make sure all instructions and results are supported.
BraketSimulator._combine_operations
— Function_combine_operations(program, shots::Int) -> Program
Combine explicit instructions and basis rotation instructions (if necessary). Validate that all operations are performed on qubits within qubit_count
.
BraketSimulator._prepare_program
— Function_prepare_program(circuit_ir::OpenQasmProgram, inputs::Dict{String, <:Any}, shots::Int) -> (Program, 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 parsing and the qubit count of the circuit.
_prepare_program(circuit_ir::Program, inputs::Dict{String, <:Any}, shots::Int) -> (Program, Int)
Apply any inputs
provided for the simulation. Return the Program
(with bound parameters) and the qubit count of the circuit.
BraketSimulator._get_measured_qubits
— Function_get_measured_qubits(program, qubit_count::Int) -> Vector{Int}
Get the qubits measured by the program. If Measure
instructions are present in the program's instruction list, their targets are used to form the list of measured qubits. If not, all qubits from 0 to qubit_count-1
are measured.
BraketSimulator._compute_results
— Function_compute_results(::, simulator, program::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
:
- 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.
BraketSimulator.flip_bit
— Functionflip_bit(amp_index::Integer, bit::Integer)
Flip the bit
-th bit of amp_index
, so that 0 becomes 1 and 1 becomes 0. The first valid value of bit
is zero.
Examples
julia> amp_index = 10
10
julia> digits(amp_index, base=2, pad=6)
6-element Vector{Int64}:
0
1
0
1
0
0
julia> amp_index = BraketSimulator.flip_bit(amp_index, 1)
8
julia> digits(amp_index, base=2, pad=6)
6-element Vector{Int64}:
0
0
0
1
0
0
BraketSimulator.flip_bits
— Functionflip_bits(amp_index::Integer, to_flip)
Flip the bit
-th bit of amp_index
for every bit
in to_flip
, so that 0 becomes 1 and 1 becomes 0. The first valid value of bit
is zero.
Examples
julia> amp_index = 10
10
julia> digits(amp_index, base=2, pad=6)
6-element Vector{Int64}:
0
1
0
1
0
0
julia> amp_index = BraketSimulator.flip_bits(amp_index, (1, 3, 2))
4
julia> digits(amp_index, base=2, pad=6)
6-element Vector{Int64}:
0
0
1
0
0
0
BraketSimulator.pad_bit
— Functionpad_bit(amp_index::Integer, bit::Integer)
Insert a 0
at location bit
of amp_index
(in its bits representation). The first valid value of bit
is zero.
Examples
julia> amp_index = 10
10
julia> digits(amp_index, base=2, pad=6)
6-element Vector{Int64}:
0
1
0
1
0
0
julia> amp_index = BraketSimulator.pad_bit(amp_index, 2);
julia> digits(amp_index, base=2, pad=7)
7-element Vector{Int64}:
0
1
0
0
1
0
0
BraketSimulator.pad_bits
— Functionpad_bits(amp_index::Integer, to_pad)
Insert a 0
in amp_index
at each location bit
in the collection to_pad
. The first valid value of any bit
is zero.
Examples
julia> amp_index = 10
10
julia> digits(amp_index, base=2, pad=6)
6-element Vector{Int64}:
0
1
0
1
0
0
julia> amp_index = BraketSimulator.pad_bits(amp_index, (2, 4));
julia> digits(amp_index, base=2, pad=8)
8-element Vector{Int64}:
0
1
0
0
0
1
0
0
The indices in pad_bits
aren't adjusted based on previous indices – this can be seen in the above example, where the bit at index 4 is different before and after inserting a bit at index 2.
BraketSimulator.matrix_rep
— Functionmatrix_rep(g::Gate)
Convert g
into its matrix form, applying its argument values and any exponent it is raised to.
BraketSimulator.endian_qubits
— Functionendian_qubits(n_qubits::Int, qubit::Int)
Rotate the qubit index qubit
to match what Braket expects with the correct endianness. This has to be done because Braket and Julia have different endianness.
The first valid value for qubit
is zero, since qubits are zero-indexed.
Examples
julia> qubit = 2
2
julia> n_qubits = 5
5
julia> BraketSimulator.endian_qubits(n_qubits, qubit)
2
julia> qubit = 3
3
julia> BraketSimulator.endian_qubits(n_qubits, qubit)
1
endian_qubits(n_qubits::Int, qubits::Int...)
Rotate each qubit index in qubits
to match what Braket expects with the correct endianness. This has to be done because Braket and Julia have different endianness.
The first valid value for any element of qubits
is zero, since qubits are zero-indexed.
BraketSimulator.get_amps_and_qubits
— Functionget_amps_and_qubits(state_vec::AbstractStateVector, qubits::Int...)
Get the total number of amplitudes of state_vec
(its length) and use this to apply endian_qubits
to qubits
. This is a convenience function to automate several common operations.
The first valid value for any element of qubits
is zero, since qubits are zero-indexed.