Skip to main content
IBM Quantum Platform
This page is from the dev version of Qiskit SDK C API. Go to the stable version.

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.


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 the interactions matrix.
  • interactions – Pointer to a row-major n × n matrix of type int64_t. May be NULL only if num_qubits == 0.
  • check_input – When true, this function verifies that the matrix is symmetric and returns NULL if it is not. When false, 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 times

Entanglement:

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_blocks is not a valid, non-null pointer to a sequence of rotation_blocks_size consecutive elements of StandardGate.
  • Behavior is undefined if entanglement_blocks is not a valid, non-null pointer to a sequence of entanglement_blocks_size consecutive elements of StandardGate.
  • Behavior is undefined if settings is 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 QkNLocalSettings pointer that is the settings to be applied to the generated circuit. If NULL, the default settings are used, see QkNLocalSettings for 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 QkPauliProductRotation to 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 QkPauliProductMeasurement to 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 QkObs containing 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.

Was this page helpful?
Report a bug, typo, or request content on GitHub.