Skip to main content
IBM Quantum Platform

QkCircuit

typedef struct QkCircuit QkCircuit

The fundamental element of quantum computing is the quantum circuit. This is a computational routine that can be run, one shot at a time, on a quantum processing unit (QPU). A circuit will act on a predefined amount of quantum data (in Qiskit, we only directly support qubits) with unitary operations (gates), measurements and resets. In addition, a quantum circuit can contain operations on classical data, including real-time computations and control-flow constructs, which are executed by the controllers of the QPU. The QkCircuit struct exposes a low level interface to Qiskit’s quantum circuit data structure and exposes only what is defined in the inner data model of Qiskit. Therefore it is missing some functionality that is available in the higher level Python QuantumCircuit class.

Below is an example of a quantum circuit that makes a three-qubit Greenberger–Horne–Zeilinger (GHZ) state defined as:

ψ=(000+111)/2|\psi\rangle = \left( |000\rangle + |111\rangle \right) / \sqrt{2}
#include <qiskit.h>

// Create a circuit with three qubits and 3 classical bits
QkCircuit *qc = qk_circuit_new(3, 0);
// H gate on qubit 0, putting this qubit in a superposition of |0> + |1>.
qk_circuit_gate(qc, QkGate_H, (uint32_t[]){0}, NULL);
// A CX (CNOT) gate on control qubit 0 and target qubit 1 generating a Bell state.
qk_circuit_gate(qc, QkGate_CX, (uint32_t[]){0, 1}, NULL);
// A CX (CNOT) gate on control qubit 0 and target qubit 2 generating a GHZ state.
qk_circuit_gate(qc, QkGate_CX, (uint32_t[]){0, 2}, NULL);
// Free the created circuit.
qk_circuit_free(qc);

The circuit C API currently only supports creating circuits that contain operations defined in Qiskit’s internal Rust data model. Generally this includes only gates in the standard gate library, standard non-unitary operations (currently Barrier, Measure, Reset, and Delay) and UnitaryGate. This functionality will be expanded over time as the Rust data model is expanded to natively support more functionality.


Data Types

QkOpCount

struct QkOpCount

An individual operation count represented by the operation name and the number of instances in the circuit.

const char *name

A nul terminated string representing the operation name

size_t count

The number of instances of this operation in the circuit

QkOpCounts

struct QkOpCounts

An array of OpCount objects representing the total counts of all the operation types in a circuit.

QkOpCount *data

A array of size len containing OpCount objects for each type of operation in the circuit

size_t len

The number of elements in data

QkCircuitInstruction

struct QkCircuitInstruction

A circuit instruction representation.

This struct represents the data contained in an individual instruction in a QkCircuit. It is not a pointer to the underlying object, but contains a copy of the properties of the instruction for inspection.

char *name

The instruction name

uint32_t *qubits

A pointer to an array of qubit indices this instruction operates on.

uint32_t *clbits

A pointer to an array of clbit indices this instruction operates on.

QkParam **params

A pointer to an array of parameter values for this instruction.

uint32_t num_qubits

The number of qubits for this instruction.

uint32_t num_clbits

The number of clbits for this instruction.

uint32_t num_params

The number of parameters for this instruction.

QkCircuitDrawerConfig

struct QkCircuitDrawerConfig

The configuration options for the qk_circuit_draw function.

bool bundle_cregs

If true, bundles classical registers into single wires.

bool merge_wires

If true, merges the bottom and top lines of adjacent wires.

size_t fold

Sets the line length for wrapping the rendered text. Use 0 to auto-detect console width. Use SIZE_MAX to effectively skip wrapping altogether.


Functions

QkDelayUnit

enum QkDelayUnit

Units for circuit delays.

Values:

enumerator QkDelayUnit_S

Seconds.

enumerator QkDelayUnit_MS

Milliseconds.

enumerator QkDelayUnit_US

Microseconds.

enumerator QkDelayUnit_NS

Nanoseconds.

enumerator QkDelayUnit_PS

Picoseconds.

QkVarsMode

enum QkVarsMode

The mode to copy the classical variables, for operations that create a new circuit based on an existing one.

Values:

enumerator QkVarsMode_Alike

Each variable has the same type it had in the input.

enumerator QkVarsMode_Captures

Each variable becomes a “capture”.

enumerator QkVarsMode_Drop

Do not copy the variable data.

QkBlocksMode

enum QkBlocksMode

The mode to use to copy blocks in control-flow instructions, for operations that create a new circuit based on an existing one.

Values:

enumerator QkBlocksMode_Drop

Drop the blocks.

enumerator QkBlocksMode_Keep

Keep the blocks.

qk_circuit_new

QkCircuit *qk_circuit_new(uint32_t num_qubits, uint32_t num_clbits)

Construct a new circuit with the given number of qubits and clbits.

Example

QkCircuit *empty = qk_circuit_new(100, 100);

Parameters

  • num_qubits – The number of qubits the circuit contains.
  • num_clbits – The number of clbits the circuit contains.

Returns

A pointer to the created circuit.

qk_circuit_add_quantum_register

void qk_circuit_add_quantum_register(QkCircuit *circuit, const QkQuantumRegister *reg)

Add a quantum register to a given quantum circuit

Example

QkCircuit *qc = qk_circuit_new(0, 0);
QkQuantumRegister *qr = qk_quantum_register_new(1024, "my_little_register");
qk_circuit_add_quantum_register(qc, qr);
qk_quantum_register_free(qr);
qk_circuit_free(qc);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit and if reg is not a valid, non-null pointer to a QkQuantumRegister.

Parameters

  • circuit – A pointer to the circuit.
  • reg – A pointer to the quantum register

qk_circuit_add_classical_register

void qk_circuit_add_classical_register(QkCircuit *circuit, const QkClassicalRegister *reg)

Add a classical register to a given quantum circuit

Example

QkCircuit *qc = qk_circuit_new(0, 0);
QkClassicalRegister *cr = qk_classical_register_new(24, "my_big_register");
qk_circuit_add_classical_register(qc, cr);
qk_classical_register_free(cr);
qk_circuit_free(qc);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit and if reg is not a valid, non-null pointer to a QkClassicalRegister.

Parameters

  • circuit – A pointer to the circuit.
  • reg – A pointer to the classical register

qk_circuit_copy

QkCircuit *qk_circuit_copy(const QkCircuit *circuit)

Create a copy of a QkCircuit.

Example

QkCircuit *qc = qk_circuit_new(100, 100);
QkCircuit *copy = qk_circuit_copy(qc);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit to copy.

Returns

A new pointer to a copy of the input circuit.

qk_circuit_num_qubits

uint32_t qk_circuit_num_qubits(const QkCircuit *circuit)

Get the number of qubits the circuit contains.

Example

QkCircuit *qc = qk_circuit_new(100, 100);
uint32_t num_qubits = qk_circuit_num_qubits(qc);  // num_qubits==100

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit.

Returns

The number of qubits the circuit is defined on.

qk_circuit_num_clbits

uint32_t qk_circuit_num_clbits(const QkCircuit *circuit)

Get the number of clbits the circuit contains.

Example

QkCircuit *qc = qk_circuit_new(100, 50);
uint32_t num_clbits = qk_circuit_num_clbits(qc);  // num_clbits==50

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit.

Returns

The number of qubits the circuit is defined on.

qk_circuit_num_param_symbols

size_t qk_circuit_num_param_symbols(const QkCircuit *circuit)

Get the number of unbound symbols in QkParam objects in the circuit.

Example

QkCircuit *qc = qk_circuit_new(2, 0);
QkParam *x = qk_param_new_symbol("x");
QkParam *y = qk_param_new_symbol("y");

uint32_t q0[1] = {0};
const QkParam *rx_param[1] = {x};
const QkParam *ry_param[1] = {y};

qk_circuit_parameterized_gate(qc, QkGate_RX, q0, rx_param);
qk_circuit_parameterized_gate(qc, QkGate_RY, q0, ry_param);

// check the number of QkParam symbols
size_t num_symbols = qk_circuit_num_param_symbols(qc); // == 2

qk_param_free(x);
qk_param_free(y);
qk_circuit_free(qc);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit.

Returns

The number of unbound QkParam symbols in the circuit.

qk_circuit_free

void qk_circuit_free(QkCircuit *circuit)

Free the circuit.

Example

QkCircuit *qc = qk_circuit_new(100, 100);
qk_circuit_free(qc);

Safety

Behavior is undefined if circuit is not either null or a valid pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit to free.

qk_circuit_gate

QkExitCode qk_circuit_gate(QkCircuit *circuit, QkGate gate, const uint32_t *qubits, const double *params)

Append a QkGate to the circuit.

Example

QkCircuit *qc = qk_circuit_new(100, 0);
uint32_t qubit[1] = {0};
qk_circuit_gate(qc, QkGate_H, qubit, NULL);

Safety

The qubits and params types are expected to be a pointer to an array of uint32_t and double respectively where the length is matching the expectations for the standard gate. If the array is insufficiently long the behavior of this function is undefined as this will read outside the bounds of the array. It can be a null pointer if there are no qubits or params for a given gate. You can check qk_gate_num_qubits and qk_gate_num_params to determine how many qubits and params are required for a given gate.

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit to add the gate to.
  • gate – The StandardGate to add to the circuit.
  • qubits – The pointer to the array of uint32_t qubit indices to add the gate on. This can be a null pointer if there are no qubits for gate (e.g. QkGate_GlobalPhase).
  • params – The pointer to the array of double values to use for the gate parameters. This can be a null pointer if there are no parameters for gate (e.g. QkGate_H).

Returns

An exit code.

qk_circuit_parameterized_gate

QkExitCode qk_circuit_parameterized_gate(QkCircuit *circuit, QkGate gate, const uint32_t *qubits, const QkParam *const *params)

Append a QkGate with QkParam* parameters to the circuit.

Example

QkCircuit *qc = qk_circuit_new(100, 0);
QkParam *theta = qk_param_new_symbol("theta");
uint32_t qubit[1] = {0};
const QkParam* params[1] = {theta};
qk_circuit_parameterized_gate(qc, QkGate_RX, qubit, params); // add RX(theta) to the circuit

Safety

The qubits and params types are expected to be a pointer to an array of uint32_t and QkParam* respectively where the length is matching the expectations for the standard gate. If the array is insufficiently long the behavior of this function is undefined as this will read outside the bounds of the array. It can be a null pointer if there are no qubits or params for a given gate. You can check qk_gate_num_qubits and qk_gate_num_params to determine how many qubits and params are required for a given gate.

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit, or if any of the elements in the params array is not a valid, non-null pointer to a QkParam.

Parameters

  • circuit – A pointer to the circuit to add the gate to.
  • gate – The QkGate to add to the circuit.
  • qubits – The pointer to the array of uint32_t qubit indices to add the gate on. This can be a null pointer if there are no qubits for gate (e.g. QkGate_GlobalPhase).
  • params – The pointer to the array of QkParam* parameters to use for the gate parameters. This can be a null pointer if there are no parameters for gate (e.g. QkGate_H).

Returns

QkExitCode_Success upon successful append. Upon failure, QkExitCode_ParameterNameConflict indicates that a new parameter symbol has a name conflict with an existing one. QkExitCode_ParameterError describes other generic failures when attempting to track the parameter symbols.

qk_gate_num_qubits

uint32_t qk_gate_num_qubits(QkGate gate)

Get the number of qubits for a QkGate.

Example

uint32_t num_qubits = qk_gate_num_qubits(QkGate_CCX);

Parameters

  • gate – The QkGate to get the number of qubits for.

Returns

The number of qubits the gate acts on.

qk_gate_num_params

uint32_t qk_gate_num_params(QkGate gate)

Get the number of parameters for a QkGate.

Example

uint32_t num_params = qk_gate_num_params(QkGate_R);

Parameters

  • gate – The QkGate to get the number of qubits for.

Returns

The number of parameters the gate has.

qk_circuit_measure

QkExitCode qk_circuit_measure(QkCircuit *circuit, uint32_t qubit, uint32_t clbit)

Append a measurement to the circuit

Example

QkCircuit *qc = qk_circuit_new(100, 1);
qk_circuit_measure(qc, 0, 0);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit to add the measurement to
  • qubit – The uint32_t for the qubit to measure
  • clbit – The uint32_t for the clbit to store the measurement outcome in

Returns

An exit code.

qk_circuit_reset

QkExitCode qk_circuit_reset(QkCircuit *circuit, uint32_t qubit)

Append a reset to the circuit

Example

QkCircuit *qc = qk_circuit_new(100, 0);
qk_circuit_reset(qc, 0);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit to add the reset to
  • qubit – The uint32_t for the qubit to reset

Returns

An exit code.

qk_circuit_barrier

QkExitCode qk_circuit_barrier(QkCircuit *circuit, const uint32_t *qubits, uint32_t num_qubits)

Append a barrier to the circuit.

Example

QkCircuit *qc = qk_circuit_new(100, 1);
uint32_t qubits[5] = {0, 1, 2, 3, 4};
qk_circuit_barrier(qc, qubits, 5);

Safety

The length of the array qubits points to must be num_qubits. If there is a mismatch the behavior is undefined.

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit to add the barrier to.
  • num_qubits – The number of qubits wide the barrier is.
  • qubits – The pointer to the array of uint32_t qubit indices to add the barrier on.

Returns

An exit code.

qk_circuit_unitary

QkExitCode qk_circuit_unitary(QkCircuit *circuit, const QkComplex64 *matrix, const uint32_t *qubits, uint32_t num_qubits, bool check_input)

Append an arbitrary unitary matrix to the circuit.

Example

QkComplex64 c0 = {0, 0};  // 0+0i
QkComplex64 c1 = {1, 0};  // 1+0i

const uint32_t num_qubits = 1;
QkComplex64 unitary[2*2] = {c0, c1,  // row 0
                            c1, c0}; // row 1

QkCircuit *circuit = qk_circuit_new(1, 0);  // 1 qubit circuit
uint32_t qubit[1] = {0};  // qubit to apply the unitary on
qk_circuit_unitary(circuit, unitary, qubit, num_qubits, true);

Safety

Behavior is undefined if any of the following is violated:

  • circuit is a valid, non-null pointer to a QkCircuit
  • matrix is an aligned pointer to 4**num_qubits initialized QkComplex64 values
  • qubits is an aligned pointer to num_qubits initialized uint32_t values

Parameters

  • circuit – A pointer to the circuit to append the unitary to.
  • matrix – A pointer to the QkComplex64 array representing the unitary matrix. This must be a row-major, unitary matrix of dimension 2 ^ num_qubits x 2 ^ num_qubits. More explicitly: the (i, j)-th element is given by matrix[i * 2^n + j]. The contents of matrix are copied inside this function before being added to the circuit, so caller keeps ownership of the original memory that matrix points to and can reuse it after the call and the caller is responsible for freeing it.
  • qubits – A pointer to array of qubit indices, of length num_qubits.
  • num_qubits – The number of qubits the unitary acts on.
  • check_input – When true, the function verifies that the matrix is unitary. If set to False the caller is responsible for ensuring the matrix is unitary, if the matrix is not unitary this is undefined behavior and will result in a corrupt circuit.

Returns

An exit code.

qk_circuit_inst_unitary

void qk_circuit_inst_unitary(QkCircuit *circuit, size_t index, QkComplex64 *out)

Copy out the unitary matrix for a given instruction in the circuit.

Panics if the instruction at the given index is not a unitary.

Safety

Behavior is undefined if any of the following is violated: if circuit is not a valid, non-null pointer to a QkCircuit, if index is out of bounds for the number of instructions in the circuit, if out is not valid for 4**num_qubits writes of QkComplex64.

Parameters

  • circuit – A pointer to the circuit to get the unitary from.
  • index – The index of the instruction to get the unitary for.
  • out – Allocated and aligned pointer to write the unitary matrix to.

qk_circuit_instruction_kind

QkOperationKind qk_circuit_instruction_kind(const QkCircuit *circuit, size_t index)

Get the “kind” of circuit instruction.

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit and if index is out of bounds for the number of instructions in the circuit.

Parameters

  • circuit – A pointer to the circuit to get the instruction kind from.
  • index – The index of the instruction to get the kind for.

Returns

A QkOperationKind enum value representing the kind of instruction at the given index.

qk_circuit_count_ops

QkOpCounts qk_circuit_count_ops(const QkCircuit *circuit)

Return a list of string names for instructions in a circuit and their counts.

To properly free the memory allocated by the struct, you should call qk_opcounts_clear. Dropping the QkOpCounts struct without doing so will leave the stored array of QkOpCount allocated and produce a memory leak.

Example

QkCircuit *qc = qk_circuit_new(100, 0);
uint32_t qubits[1] = {0};
qk_circuit_gate(qc, QkGate_H, qubits, NULL);
QkOpCounts counts = qk_circuit_count_ops(qc);
// .. once done
qk_opcounts_clear(&counts);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit to get the counts for.

Returns

An QkOpCounts struct containing the circuit operation counts.

qk_circuit_num_instructions

size_t qk_circuit_num_instructions(const QkCircuit *circuit)

Return the total number of instructions in the circuit.

Example

QkCircuit *qc = qk_circuit_new(100, 0);
uint32_t qubit[1] = {0};
qk_circuit_gate(qc, QkGate_H, qubit, NULL);
size_t num = qk_circuit_num_instructions(qc); // 1

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit to get the total number of instructions for.

Returns

The total number of instructions in the circuit.

qk_circuit_get_instruction

void qk_circuit_get_instruction(const QkCircuit *circuit, size_t index, QkCircuitInstruction *instruction)

Return the instruction details for an instruction in the circuit.

This function is used to get the instruction details for a given instruction in the circuit.

This function allocates memory internally for the provided QkCircuitInstruction and thus you are responsible for calling qk_circuit_instruction_clear to free it.

Example

QkCircuitInstruction inst;
QkCircuit *qc = qk_circuit_new(100, 0);
uint32_t qubit[1] = {0};
qk_circuit_gate(qc, QkGate_H, qubit, NULL);
qk_circuit_get_instruction(qc, 0, &inst);
qk_circuit_instruction_clear(&inst);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit. The value for index must be less than the value returned by qk_circuit_num_instructions otherwise this function will panic. Behavior is undefined if instruction is not a valid, non-null pointer to a memory allocation with sufficient space for a QkCircuitInstruction.

Parameters

  • circuit – A pointer to the circuit to get the instruction details for.
  • index – The instruction index to get the instruction details of.
  • instruction – A pointer to where to write out the QkCircuitInstruction

qk_circuit_pauli_product_rotation

void qk_circuit_pauli_product_rotation(QkCircuit *circuit, const QkPauliProductRotation *rotation, const uint32_t *qubits)

Apply a QkPauliProductRotation to a circuit.

Example

// build a IXYZ Pauli rotation
bool x[4] = {false, true, true, false};
bool z[4] = {false, false, true, true};
QkParam *angle = qk_param_from_double(1.0);
QkPauliProductRotation rotation = {x, z, 4, angle};
// append it to a circuit
QkCircuit *circuit = qk_circuit_new(10, 1);
uint32_t qubits[4] = {0, 1, 2, 3};
qk_circuit_pauli_product_rotation(circuit, &rotation, qubits);
// do something with the circuit... and then free it
qk_param_free(angle);
qk_circuit_free(circuit);

Safety

Behavior is undefined if any of the following is violated:

  • circuit is a valid, non-null pointer to a QkCircuit
  • rotation is a valid, non-null pointer to a coherent QkPauliProductRotation. Specifically, the rotation->z and rotation->x data arrays must be readable for rotation->len elements.
  • qubits is an aligned pointer to rotation->len initialized uint32_t values.

Parameters

  • circuit – The circuit to apply the operation to.
  • rotation – A pointer to the QkPauliProductRotation to apply.
  • qubits – A pointer to the qubit array.

qk_circuit_inst_pauli_product_rotation

QkExitCode qk_circuit_inst_pauli_product_rotation(const QkCircuit *circuit, size_t index, QkPauliProductRotation *instruction)

Get the QkPauliProductRotation data from a circuit instruction.

For a circuit with a QkPauliProductRotation instruction at index index, this function will populate the instruction pointer with a copy of QkPauliProductRotation data. Note that this data lives independently of the circuit and must be freed manually with qk_pauli_product_rotation_clear.

If the instruction at the provided index is not a QkPauliProductRotation, this function will return QkExitCode_InvalidOperationKind error. You can verify that the instruction has the right kind using qk_circuit_instruction_kind.

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit. The value for index must be less than the value returned by qk_circuit_num_instructions otherwise this function will panic. Behavior is undefined if instruction is not a valid, non-null pointer to a memory allocation with sufficient space for a QkPauliProductRotation.

Parameters

  • circuit – A pointer to the circuit to retrieve the instruction details from.
  • index – The circuit instruction index.
  • instruction – A pointer to an allocated QkPauliProductRotation to store the data.

Returns

QkExitCode_Success if the data was written into the instruction, or QkExitCode_InvalidOperationKind if the index did not point to a QkPauliProductRotation.

qk_circuit_pauli_product_measurement

void qk_circuit_pauli_product_measurement(QkCircuit *circuit, const QkPauliProductMeasurement *measurement, const uint32_t *qubits, uint32_t clbit)

Apply a QkPauliProductMeasurement to a circuit.

Example

// build a XZ Pauli measurement
bool x[2] = {true, false};
bool z[2] = {false, true};
QkPauliProductMeasurement measure = {x, z, 2, false};
// append it to a circuit
QkCircuit *circuit = qk_circuit_new(10, 1);
uint32_t qubits[2] = {0, 2};
uint32_t clbit = 0;
qk_circuit_pauli_product_measurement(circuit, &measure, qubits, clbit);
// do something with the circuit... and then free it
qk_circuit_free(circuit);

Safety

Behavior is undefined if any of the following is violated:

  • circuit is a valid, non-null pointer to a QkCircuit
  • measurement is a valid, non-null pointer to a coherent QkPauliProductMeasurement. Specifically, the measurement->z and measurement->x data arrays must be readable for measurement->len elements.
  • qubits is an aligned pointer to rotation->len initialized uint32_t values.

Parameters

  • circuit – The circuit to apply the operation to.
  • measurement – A pointer to the QkPauliProductMeasurement to apply.
  • qubits – A pointer to the qubit array.
  • clbit – A single uint32_t specifying the measurement qubit.

qk_circuit_inst_pauli_product_measurement

QkExitCode qk_circuit_inst_pauli_product_measurement(const QkCircuit *circuit, size_t index, QkPauliProductMeasurement *instruction)

Get the QkPauliProductMeasurement data from a circuit instruction.

For a circuit with a QkPauliProductMeasurement instruction at index index, this function will populate the instruction pointer with a copy of QkPauliProductMeasurement data. Note that this data lives independently of the circuit must be freed manually with qk_pauli_product_measurement_clear.

If the instruction at the provided index is not a QkPauliProductMeasurement, this function will return QkExitCode_InvalidOperationKind error. Verify that the instruction is of the correct kind using qk_circuit_instruction_kind.

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit. The value for index must be less than the value returned by qk_circuit_num_instructions otherwise this function will panic. Behavior is undefined if instruction is not a valid, non-null pointer to a memory allocation with sufficient space for a QkPauliProductMeasurement.

Parameters

  • circuit – A pointer to the circuit to retrieve the instruction details from.
  • index – The circuit instruction index.
  • instruction – A pointer to an allocated QkPauliProductMeasurement to store the data.

Returns

QkExitCode_Success if the data was written into the instruction, or QkExitCode_InvalidOperationKind if the index did not point to a QkPauliProductMeasurement.

qk_circuit_instruction_clear

void qk_circuit_instruction_clear(QkCircuitInstruction *inst)

Clear the data in circuit instruction object.

This function doesn’t free the allocation for the provided QkCircuitInstruction pointer, it only frees the internal allocations for the data contained in the instruction. You are responsible for allocating and freeing the actual allocation used to store a QkCircuitInstruction.

Example

QkCircuitInstruction *inst = malloc(sizeof(QkCircuitInstruction));
QkCircuit *qc = qk_circuit_new(100, 0);
uint32_t q0[1] = {0};
qk_circuit_gate(qc, QkGate_H, q0, NULL);
qk_circuit_get_instruction(qc, 0, inst);
qk_circuit_instruction_clear(inst); // clear internal allocations
free(inst); // free struct
qk_circuit_free(qc); // free the circuit

Safety

Behavior is undefined if inst is not a valid, non-null pointer to a QkCircuitInstruction.

Parameters

  • inst – A pointer to the instruction to free.

qk_opcounts_clear

void qk_opcounts_clear(QkOpCounts *op_counts)

Clear the content in a circuit operation count list.

Safety

Behavior is undefined if op_counts is not the object returned by qk_circuit_count_ops.

Parameters

  • op_counts – The returned op count list from qk_circuit_count_ops.

qk_circuit_delay

QkExitCode qk_circuit_delay(QkCircuit *circuit, uint32_t qubit, double duration, QkDelayUnit unit)

Append a delay instruction to the circuit.

Example

QkCircuit *qc = qk_circuit_new(1, 0);
qk_circuit_delay(qc, 0, 100.0, QkDelayUnit_NS);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit to add the delay to.
  • qubit – The uint32_t index of the qubit to apply the delay to.
  • duration – The duration of the delay.
  • unit – An enum representing the unit of the duration.

Returns

An exit code.

qk_circuit_draw

char *qk_circuit_draw(const QkCircuit *circuit, const QkCircuitDrawerConfig *config)

Draw the circuit as text.

Example

QkCircuit *circuit = qk_circuit_new(2, 1);

qk_circuit_gate(circuit, QkGate_H, (uint32_t[]){0}, NULL);
qk_circuit_gate(circuit, QkGate_CX, (uint32_t[]){0, 1}, NULL);
qk_circuit_measure(circuit, 0, 0);
qk_circuit_measure(circuit, 1, 0);

QkCircuitDrawerConfig config = {false, true, 0};

char *circ_str = qk_circuit_draw(circuit, &config);

printf("%s", circ_str);

qk_str_free(circ_str);
qk_circuit_free(circuit);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit, or if config is not NULL and a non-valid pointer to a QkCircuitDrawerConfig struct.

Parameters

  • circuit – A pointer to the circuit to draw.

  • config – A pointer to the QkCircuitDrawerConfig structure or NULL. If NULL, the drawer will use these defaults:

    • bundle_cregs = true
    • merge_wires = true
    • fold = 0

Returns

A pointer to a null-terminated string containing the circuit representation. You must use qk_str_free to release the allocated memory when done.

qk_circuit_to_dag

QkDag *qk_circuit_to_dag(const QkCircuit *circuit)

Convert a given circuit to a DAG.

The new DAG is copied from the circuit; the original circuit reference is still owned by the caller and still required to be freed with qk_circuit_free. You must free the returned DAG with qk_dag_free when done with it.

Example

QkCircuit *qc = qk_circuit_new(0, 0);
QkQuantumRegister *qr = qk_quantum_register_new(3, "qr");
qk_circuit_add_quantum_register(qc, qr);
qk_quantum_register_free(qr);

QkDag *dag = qk_circuit_to_dag(qc);

qk_dag_free(dag);
qk_circuit_free(qc);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit from which to create the DAG.

Returns

A pointer to the new DAG.

qk_circuit_copy_empty_like

QkCircuit *qk_circuit_copy_empty_like(const QkCircuit *circuit, QkVarsMode vars_mode, QkBlocksMode blocks_mode)

Return a copy of self with the same structure but empty.

That structure includes:

  • global phase
  • all the qubits and clbits, including the registers.

Example

QkCircuit *qc = qk_circuit_new(10, 10);
for (int i = 0; i < 10; i++) {
    qk_circuit_measure(qc, i, i);
    uint32_t qubits[1] = {i};
    qk_circuit_gate(qc, QkGate_H, qubits, NULL);
}

// As the circuit does not contain any control-flow instructions,
// vars_mode and blocks_mode do not have any effect.
QkCircuit *copy = qk_circuit_copy_empty_like(qc, QkVarsMode_Alike, QkBlocksMode_Drop);

size_t num_copy_instructions = qk_circuit_num_instructions(copy); // 0

// do something with the copy

qk_circuit_free(qc);
qk_circuit_free(copy);

Safety

Behavior is undefined if circuit is not a valid, non-null pointer to a QkCircuit.

Parameters

  • circuit – A pointer to the circuit to copy.
  • vars_mode – The mode for handling classical variables.
  • blocks_mode – The mode for handling blocks.

Returns

The pointer to the copied circuit.

qk_circuit_to_python

PyObject *qk_circuit_to_python(QkCircuit *qc)

Pass ownership of a QkCircuit object to Python.

The resulting Python object is not QuantumCircuit, it is the inner CircuitData, which is typically accessed as QuantumCircuit._data. You can use qk_circuit_to_python_full to produce a complete QuantumCircuit object.

It is not safe to use the QkCircuit pointer after calling this function. In particular, you should not attempt to clear or free it. The caller must own the QkCircuit, not hold a borrowed reference (for example, a QkCircuit * retrieved from qk_circuit_borrow_from_python is not owned).

Safety

The caller must be attached to a Python interpreter. Behavior is undefined if circuit is not a valid non-null pointer to an initialized and owned QkCircuit.

Parameters

  • qc – The owned object.

Returns

An owned Python reference to the object.

qk_circuit_to_python_full

PyObject *qk_circuit_to_python_full(QkCircuit *qc)

Pass ownership of a QkCircuit object to Python and create a complete QuantumCircuit.

This includes additional Python-space logic to produce the complete QuantumCircuit, since QkCircuit corresponds only to the internal QuantumCircuit._data field.

It is not safe to use the QkCircuit pointer after calling this function. In particular, you should not attempt to clear or free it. The caller must own the QkCircuit, not hold a borrowed reference (for example, a QkCircuit * retrieved from qk_circuit_borrow_from_python is not owned).

Safety

The caller must be attached to a Python interpreter. Behavior is undefined if circuit is not a valid non-null pointer to an initialized and owned QkCircuit.

Parameters

  • qc – The owned object.

Returns

An owned Python reference to the object.

qk_circuit_borrow_from_python

QkCircuit *qk_circuit_borrow_from_python(PyObject *ob)

Retrieve a QkCircuit pointer from a Python object.

Note that the input to this function should not be QuantumCircuit, but the output of QuantumCircuit._data. This is necessary to enforce correct reference-counting semantics.

This borrows a Python reference and extracts the QkCircuit pointer for it, if it is of the correct type. The returned pointer is borrowed from the ob pointer. If the PyObject is not the correct type, the return value is NULL and the exception state of the Python interpreter is set.

You must be attached to a Python interpreter to call this function.

You can also use qk_circuit_convert_from_python, which is logically the exact same as this function, but can be directly used as a “converter” function for the PyArg_Parse* family of Python converter functions.

Safety

The caller must be attached to a Python interpreter. Behavior is undefined if ob is not a valid non-null pointer to a Python object.

Parameters

  • ob – A borrowed Python object.

Returns

A pointer to the native object, or NULL if the Python object is the wrong type.

qk_circuit_convert_from_python

int qk_circuit_convert_from_python(PyObject *object, void *address)

Retrieve a QkCircuit pointer from a Python object.

Note that the input to this function should not be QuantumCircuit, but the output of QuantumCircuit._data. This is necessary to enforce correct reference-counting semantics.

This borrows a Python reference and extracts the QkCircuit pointer for it into address, if it is of the correct type. The returned pointer is borrowed from the object pointer. If the PyObject is not the correct type, the return value is 0, the exception state of the Python interpreter is set, and address is unchanged.

You must be attached to a Python interpreter to call this function.

You can also use qk_circuit_borrow_from_python, which is logically the exact same as this, but with a more natural signature for direct usage.

Safety

The caller must be attached to a Python interpreter. Behavior is undefined if object is not a valid non-null pointer to a Python object, or if address is not a pointer to writeable data of the correct type.

Parameters

  • object – A borrowed Python object.
  • address – The location to write the output to.

Returns

1 on success, 0 on failure.

qk_quantum_register_to_python

PyObject *qk_quantum_register_to_python(QkQuantumRegister *qr)

Pass ownership of a QkQuantumRegister object to Python.

It is not safe to use the QkQuantumRegister pointer after calling this function. In particular, you should not attempt to clear or free it. The caller must own the QkQuantumRegister, not hold a borrowed reference (for example, a QkQuantumRegister * retrieved from qk_quantum_register_borrow_from_python is not owned).

Safety

The caller must be attached to a Python interpreter. Behavior is undefined if qr is not a valid non-null pointer to an initialized and owned QkQuantumRegister.

Parameters

  • qr – The owned object.

Returns

An owned Python reference to the object.

qk_quantum_register_borrow_from_python

const QkQuantumRegister *qk_quantum_register_borrow_from_python(PyObject *ob)

Retrieve a QkQuantumRegister pointer from a Python object.

This borrows a Python reference and extracts the QkQuantumRegister pointer for it, if it is of the correct type. The returned pointer is borrowed from the ob pointer. If the PyObject is not the correct type, the return value is NULL and the exception state of the Python interpreter is set.

You must be attached to a Python interpreter to call this function.

You can also use qk_quantum_register_convert_from_python, which is logically the exact same as this function, but can be directly used as a “converter” function for the PyArg_Parse* family of Python converter functions.

Safety

The caller must be attached to a Python interpreter. Behavior is undefined if ob is not a valid non-null pointer to a Python object.

Parameters

  • ob – A borrowed Python object.

Returns

A pointer to the native object, or NULL if the Python object is the wrong type.

qk_quantum_register_convert_from_python

int qk_quantum_register_convert_from_python(PyObject *object, void *address)

Retrieve a QkQuantumRegister pointer from a Python object.

This borrows a Python reference and extracts the QkQuantumRegister pointer for it into address, if it is of the correct type. The returned pointer is borrowed from the object pointer. If the PyObject is not the correct type, the return value is 0, the exception state of the Python interpreter is set, and address is unchanged.

You must be attached to a Python interpreter to call this function.

You can also use qk_quantum_register_borrow_from_python, which is logically the exact same as this, but with a more natural signature for direct usage.

Safety

The caller must be attached to a Python interpreter. Behavior is undefined if object is not a valid non-null pointer to a Python object, or if address is not a pointer to writeable data of the correct type.

Parameters

  • object – A borrowed Python object.
  • address – The location to write the output to.

Returns

1 on success, 0 on failure.

qk_classical_register_to_python

PyObject *qk_classical_register_to_python(QkClassicalRegister *cr)

Pass ownership of a QkClassicalRegister object to Python.

It is not safe to use the QkClassicalRegister pointer after calling this function. In particular, you should not attempt to clear or free it. The caller must own the QkClassicalRegister, not hold a borrowed reference (for example, a QkClassicalRegister * retrieved from qk_classical_register_borrow_from_python is not owned).

Safety

The caller must be attached to a Python interpreter. Behavior is undefined if cr is not a valid non-null pointer to an initialized and owned QkClassicalRegister.

Parameters

  • cr – The owned object.

Returns

An owned Python reference to the object.

qk_classical_register_borrow_from_python

const QkClassicalRegister *qk_classical_register_borrow_from_python(PyObject *ob)

Retrieve a QkClassicalRegister pointer from a Python object.

This borrows a Python reference and extracts the QkClassicalRegister pointer for it, if it is of the correct type. The returned pointer is borrowed from the ob pointer. If the PyObject is not the correct type, the return value is NULL and the exception state of the Python interpreter is set.

You must be attached to a Python interpreter to call this function.

You can also use qk_classical_register_convert_from_python, which is logically the exact same as this function, but can be directly used as a “converter” function for the PyArg_Parse* family of Python converter functions.

Safety

The caller must be attached to a Python interpreter. Behavior is undefined if ob is not a valid non-null pointer to a Python object.

Parameters

  • ob – A borrowed Python object.

Returns

A pointer to the native object, or NULL if the Python object is the wrong type.

qk_classical_register_convert_from_python

int qk_classical_register_convert_from_python(PyObject *object, void *address)

Retrieve a QkClassicalRegister pointer from a Python object.

This borrows a Python reference and extracts the QkClassicalRegister pointer for it into address, if it is of the correct type. The returned pointer is borrowed from the object pointer. If the PyObject is not the correct type, the return value is 0, the exception state of the Python interpreter is set, and address is unchanged.

You must be attached to a Python interpreter to call this function.

You can also use qk_classical_register_borrow_from_python, which is logically the exact same as this, but with a more natural signature for direct usage.

Safety

The caller must be attached to a Python interpreter. Behavior is undefined if object is not a valid non-null pointer to a Python object, or if address is not a pointer to writeable data of the correct type.

Parameters

  • object – A borrowed Python object.
  • address – The location to write the output to.

Returns

1 on success, 0 on failure.

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