Circuit Library
The Qiskit circuit library contains functions and higher-level building blocks for building commonly used quantum circuits.
Data types
QkPauliProductRotation
struct QkPauliProductRotation
A representation of Pauli product rotation data.
A Pauli product rotation implements a rotation of an angle about an axis defined by a Pauli product on len qubits. The Pauli here is represented in ZX format with two Boolean arrays representing the Z and X components.
bool *z
Pointer to an length-len array of Z components.
bool *x
Pointer to an length-len array of X components.
size_t len
The number of Pauli terms.
QkParam *angle
The rotation angle.
QkPauliProductMeasurement
struct QkPauliProductMeasurement
A representation of Pauli product measurement data.
A Pauli product measurement implements a projection onto the eigenspace of the defined Pauli product on len qubits. The Pauli here is represented in ZX format with two Boolean arrays representing the Z and X components and can include a minus sign, indicated by flip_outcome.
bool *z
Pointer to an length-len array of Z components.
bool *x
Pointer to an length-len array of X components.
size_t len
The number of Pauli terms.
bool flip_outcome
Whether the measurement outcome has a minus sign.
QkNLocalSettings
struct QkNLocalSettings
Settings for generating a n-local variational circuit.
This contains the entanglement strategy (entanglement_strategy), the repetitions of the rotation and entanglement layers (reps), the parameter prefix for gates that have parameters (parameter_prefix), whether it’s wanted to add barriers after each layer (insert_barriers) and if it’s wanted to skip the last layer (skip_final_rotation_layer)
It’s the responsibility of the user that the data is coherent, see also the below section on safety.
Safety
parameter_prefix must be a pointer to memory that contains a valid nul terminator at the end of the string. It also must be valid for reads of bytes up to and including the nul terminator.
QkEntanglementStrategy entanglement_strategy
The entanglement strategy to be used in the generated circuit. See QkEntanglementStrategy for more details.
size_t reps
Specifies how often the rotation blocks and entanglement blocks are repeated.
const char *parameter_prefix
The prefix used for the default parameters generated.
bool insert_barriers
If true, barriers are inserted in between each layer. If false, no barriers are inserted.
bool skip_final_rotation_layer
Whether a final rotation layer is added to the circuit.
QkEntanglementStrategy
enum QkEntanglementStrategy
Enum representing all the possible strategies for n_local entanglement blocks.
Values:
enumerator QkEntanglementStrategy_Full
Entanglement where each qubit is entangled with all the others.
enumerator QkEntanglementStrategy_Linear
Entanglement where qubit is entangled with qubit for all where is the total number of qubits.
enumerator QkEntanglementStrategy_ReverseLinear
Entanglement where qubit is entangled with qubit for all where is the total number of qubits.
enumerator QkEntanglementStrategy_Circular
Entanglement that behaves the same as linear entanglement but with an additional entanglement of the first and last qubit before the linear part.
enumerator QkEntanglementStrategy_Pairwise
Entanglement where one layer contains a qubit entangled with qubit , for all even values of , and then a second layer where a qubit is entangled with qubit , for all odd values of .
enumerator QkEntanglementStrategy_Sca
Entanglement shifted-circular-alternating. It’s a generalized and modified version of the proposed circuit 14 in Sim et al.
It consists of circular entanglement where the “long” entanglement connecting the first with the last qubit is shifted by one each block.
Furthermore the role of control and target qubits are swapped every block (therefore alternating).
Functions
qk_circuit_library_iqp
QkCircuit *qk_circuit_library_iqp(uint32_t num_qubits, const int64_t *interactions, bool check_input)
Generate an Instantaneous Quantum Polynomial (IQP) circuit from an integer interaction matrix.
The interactions matrix is interpreted as an n × n row-major array of 64-bit integers, where n = num_qubits. The diagonal entries set T-like phase powers, and the upper triangle encodes two-qubit CPhase interactions.
Safety
If num_qubits > 0, interactions must be a valid, non-null pointer to at least num_qubits * num_qubits contiguous int64_t values in row-major order. The memory pointed to by interactions must be properly aligned, readable for the duration of this call, and not mutably aliased. Passing an invalid pointer or a buffer that is too small results in undefined behaviour.
Parameters
- num_qubits – Number of logical qubits (
n). Must match the dimension of theinteractionsmatrix. - interactions – Pointer to a row-major
n × nmatrix of typeint64_t. May be NULL only ifnum_qubits == 0. - check_input – When
true, this function verifies that the matrix is symmetric and returnsNULLif it is not. Whenfalse, no additional validation is performed.
Returns
A newly allocated QkCircuit* on success (caller must free with qk_circuit_free), or NULL if num_qubits > 0 and interactions is NULL, or if check_input is true and the matrix is not symmetric.
qk_circuit_library_random_iqp
QkCircuit *qk_circuit_library_random_iqp(uint32_t num_qubits, int64_t seed)
Generate a random Instantaneous Quantum Polynomial (IQP) circuit.
This constructs a random symmetric integer interaction matrix internally and uses it to build an IQP circuit, mirroring the Python qiskit.circuit.library.IQP constructor.
Parameters
- num_qubits – Number of qubits.
- seed – RNG seed. If negative, entropy is drawn from the OS; otherwise, the given value is used as a deterministic seed.
Returns
A newly allocated QkCircuit* (caller must free with qk_circuit_free).
qk_circuit_library_n_local
QkCircuit *qk_circuit_library_n_local(uint32_t num_qubits, const QkGate *rotation_blocks, size_t rotation_blocks_size, const QkGate *entanglement_blocks, size_t entanglement_blocks_size, const QkNLocalSettings *settings)
Construct an n-local variational circuit.
The structure of the n-local circuit are alternating rotation and entanglement layers. In both layers, parameterized circuit-blocks act on the circuit in a defined way. In the rotation layer, the blocks are applied stacked on top of each other, while in the entanglement layer according to the entanglement strategy. The circuit blocks can have arbitrary sizes (smaller equal to the number of qubits in the circuit). Each layer is repeated reps times, and by default a final rotation layer is appended.
For instance, a rotation block on 2 qubits and an entanglement block on 4 qubits using QkEntanglementStrategy_Linear entanglement yields the following circuit.
┌──────┐ ░ ┌──────┐ ░ ┌──────┐
┤0 ├─░─┤0 ├──────────────── ... ─░─┤0 ├
│ Rot │ ░ │ │┌──────┐ ░ │ Rot │
┤1 ├─░─┤1 ├┤0 ├──────── ... ─░─┤1 ├
├──────┤ ░ │ Ent ││ │┌──────┐ ░ ├──────┤
┤0 ├─░─┤2 ├┤1 ├┤0 ├ ... ─░─┤0 ├
│ Rot │ ░ │ ││ Ent ││ │ ░ │ Rot │
┤1 ├─░─┤3 ├┤2 ├┤1 ├ ... ─░─┤1 ├
├──────┤ ░ └──────┘│ ││ Ent │ ░ ├──────┤
┤0 ├─░─────────┤3 ├┤2 ├ ... ─░─┤0 ├
│ Rot │ ░ └──────┘│ │ ░ │ Rot │
┤1 ├─░─────────────────┤3 ├ ... ─░─┤1 ├
└──────┘ ░ └──────┘ ░ └──────┘
| |
+---------------------------------+
repeated reps timesEntanglement:
The entanglement describes the connections of the gates in the entanglement layer. For a two-qubit gate for example, the entanglement contains pairs of qubits on which the gate should acts, e.g. [[ctrl0, target0], [ctrl1, target1], ...]. To know more about the available entanglement strategies see QkEntanglementStrategy.
Example
size_t num_qubits = 2;
QkGate rotation_blocks[1] = {QkGate_H};
QkGate entanglement_blocks[1] = {QkGate_CRX};
QkNLocalSettings settings = qk_circuit_library_n_local_settings_default();
settings.reps = 2;
// For this example we use QkEntanglementStrategy_Linear since
// the default is QkEntanglementStrategy_Full
settings.entanglement_strategy = QkEntanglementStrategy_Linear;
QkCircuit *qc = qk_circuit_library_n_local(num_qubits, rotation_blocks, 1,
entanglement_blocks, 1, &settings);
qk_circuit_free(qc);Safety
- Behavior is undefined if
rotation_blocksis not a valid, non-null pointer to a sequence ofrotation_blocks_sizeconsecutive elements ofStandardGate. - Behavior is undefined if
entanglement_blocksis not a valid, non-null pointer to a sequence ofentanglement_blocks_sizeconsecutive elements ofStandardGate. - Behavior is undefined if
settingsis not a valid, non-null pointer.
Parameters
- num_qubits – The number of qubits of the circuit.
- rotation_blocks – The blocks used in the rotation layers.
- rotation_blocks_size – Length of the array of rotation blocks provided.
- entanglement_blocks – The blocks used in the entanglement layers.
- entanglement_blocks_size – Length of the list of entanglement blocks provided.
- settings – A
QkNLocalSettingspointer that is the settings to be applied to the generated circuit. IfNULL, the default settings are used, seeQkNLocalSettingsfor more details.
Returns
A pointer to the generated circuit.
qk_circuit_library_n_local_settings_default
QkNLocalSettings qk_circuit_library_n_local_settings_default(void)
Generate default options for qk_circuit_library_n_local.
Returns
A QkNLocalSettings object with default settings.
qk_pauli_product_rotation_clear
void qk_pauli_product_rotation_clear(QkPauliProductRotation *inst)
Clear the internal data of Rust-allocated QkPauliProductRotation.
This frees the memory of the z and x arrays and frees the angle. This function should only be called for QkPauliProductRotation objects whose data has been populated by Rust.
Example
// let `circuit` be a QkCircuit* and `index` a size_t at the position of a QkPauliProductRotation
QkPauliProductRotation inst;
// query the QkPauliProductRotation data
assert(qk_circuit_operation_kind(circuit, index) == QkOperationKind_PauliProductRotation);
qk_circuit_inst_pauli_product_rotation(circuit, index, &inst);
// do something with `inst`, and then clear the Rust-allocated data
qk_pauli_product_rotation_clear(&inst);In contrast, this function should not be called if C already takes care of clearing the data.
bool z[4] = {false, false, true, true};
bool x[4] = {false, true, true, false};
QkParam *angle = qk_param_from_double(1.0);
QkPauliProductRotation rotation = {z, x, 4, angle};
// since this data is allocated by C, we do not call `qk_pauli_product_rotation_clear(&rotation)`!
qk_param_free(angle);Safety
Behavior is undefined if inst is not a valid, non-null pointer to a QkPauliProductRotation, or if the internal data of QkPauliProductRotation is incoherent.
Parameters
- inst – A pointer to the
QkPauliProductRotationto clear.
qk_pauli_product_measurement_clear
void qk_pauli_product_measurement_clear(QkPauliProductMeasurement *inst)
Clear the internal data of Rust-allocated QkPauliProductMeasurement.
This frees the memory of the z and x arrays. This function should only be called for QkPauliProductMeasurement objects whose data has been populated by Rust.
Example
// let `circuit` be a QkCircuit* and `index` a size_t at the position
// of a QkPauliProductMeasurement
QkPauliProductMeasurement inst;
// query the QkPauliProductMeasurement data
assert(qk_circuit_operation_kind(circuit, index) == QkOperationKind_PauliProductMeasurement);
qk_circuit_inst_pauli_product_measurement(circuit, index, &inst);
// do something with `inst`, and then clear the Rust-allocated data
qk_pauli_product_measurement_clear(&inst);In contrast, this function should not be called if C already takes care of clearing the data.
bool z[4] = {false, false, true, true};
bool x[4] = {false, true, true, false};
QkPauliProductMeasurement inst = {z, x, 4, true};
// since this data is allocated by C, we do not call `qk_pauli_product_measurement_clear(&inst)`Safety
Behavior is undefined if inst is not a valid, non-null pointer to a QkPauliProductMeasurement, or if the internal data of QkPauliProductMeasurement is incoherent.
Parameters
- inst – A pointer to the
QkPauliProductMeasurementto clear.
qk_circuit_library_quantum_volume
QkCircuit *qk_circuit_library_quantum_volume(uint32_t num_qubits, size_t depth, int64_t seed)
Generate a Quantum Volume model circuit
The model circuits are random instances of circuits used to measure the Quantum Volume metric, as introduced in [1]. The model circuits consist of layers of Haar random elements of SU(4) applied between corresponding pairs of qubits in a random bipartition.
This function is multithreaded and will launch a thread pool with threads equal to the number of CPUs by default. You can tune the number of threads with the RAYON_NUM_THREADS environment variable. For example, setting RAYON_NUM_THREADS=4 would limit the thread pool to 4 threads.
[1] A. Cross et al. Validating quantum computers using randomized model circuits, Phys. Rev. A 100, 032328 (2019). arXiv:1811.12926
Example
QkCircuit *qc = qk_circuit_library_quantum_volume(10, 10, -1)Parameters
- num_qubits – The number qubits to use for the generated circuit.
- depth – The number of layers for the generated circuit.
- seed – An RNG seed used for generating the random SU(4) matrices used in the output circuit. If the provided number is negative the seed used will be soured from system entropy.
Returns
A pointer to the quantum volume circuit.
qk_circuit_library_suzuki_trotter
QkCircuit *qk_circuit_library_suzuki_trotter(const QkObs *op, uint32_t order, uint32_t reps, double time, bool preserve_order, bool insert_barriers)
Generate a circuit using the higher order Suzuki-Trotter product formula from an observable.
The Suzuki-Trotter formulas improve the error of the Lie-Trotter approximation. In this implementation, the operators are provided as sum terms of a Pauli operator. Higher order decompositions are based on recursions, see Ref. [1] for more details.
Example
QkObs *obs = qk_obs_zero(1);
QkBitTerm op1_bits[1] = {QkBitTerm_X};
QkObsTerm term1 = {(QkComplex64){1.0, 0.0}, 1, op1_bits, (uint32_t[1]){0}, 1};
qk_obs_add_term(obs, &term1);
QkBitTerm op2_bits[1] = {QkBitTerm_Y};
QkObsTerm term2 = {(QkComplex64){1.0, 0.0}, 1, op2_bits, (uint32_t[1]){0}, 1};
qk_obs_add_term(obs, &term2);
QkCircuit *qc = qk_circuit_library_suzuki_trotter(obs, 2, 1, 0.1, true, false);
qk_obs_free(obs);
qk_circuit_free(qc);Safety
Behavior is undefined op is not a valid, non-null pointer to a QkObs.
References
[1]: D. Berry, G. Ahokas, R. Cleve and B. Sanders, “Efficient quantum algorithms for simulating sparse Hamiltonians” (2006). arXiv:quant-ph/0508139
[2]: N. Hatano and M. Suzuki, “Finding Exponential Product Formulas of Higher Orders” (2005). arXiv:math-ph/0506007
Parameters
- op – The
QkObscontaining the sum of the Pauli terms. - order – The order of the product formula.
- reps – The number of time steps.
- time – The evolution time.
- preserve_order – If
false, allows reordering the terms of the operator to potentially yield a shallower evolution circuit. Not relevant when synthesizing an observable with a single term. - insert_barriers – Whether to insert barriers between the terms evolutions.
Returns
A pointer to the generated circuit.