QkDag
typedef struct QkDag QkDagThe QkDag struct exposes a low level interface to the Qiskit transpiler’s directed acyclic graph (DAG) representation of a quantum circuit for use in transpiler passes. It 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 DAGCircuit class.
The C API currently only supports building DAGs 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
QkDagNodeType
enum QkDagNodeType
The type of node in a QkDag.
Operation nodes represent an applied instruction. The rest of the nodes are considered “wire” nodes and represent the endpoints of the DAG’s data dependency chains.
Values:
enumerator QkDagNodeType_Operation
Operation node.
enumerator QkDagNodeType_QubitIn
Qubit wire start node.
enumerator QkDagNodeType_QubitOut
Qubit wire end node.
enumerator QkDagNodeType_ClbitIn
Clbit wire start node.
enumerator QkDagNodeType_ClbitOut
Clbit wire end node.
enumerator QkDagNodeType_VarIn
Classical variable wire start node.
enumerator QkDagNodeType_VarOut
Classical variable wire end node.
QkOperationKind
enum QkOperationKind
The operation’s kind.
This is returned when querying a particular node in the graph with qk_dag_op_node_kind, and is intended to allow the caller to dispatch (e.g. via a “switch”) calls specific to the contained operation’s kind.
Values:
enumerator QkOperationKind_Gate
enumerator QkOperationKind_Barrier
enumerator QkOperationKind_Delay
enumerator QkOperationKind_Measure
enumerator QkOperationKind_Reset
enumerator QkOperationKind_Unitary
enumerator QkOperationKind_PauliProductMeasurement
enumerator QkOperationKind_ControlFlow
enumerator QkOperationKind_Unknown
This variant is used as an opaque type for operations not yet implemented in the native data model.
QkDagNeighbors
struct QkDagNeighbors
A struct for storing successors and predecessors information retrieved from qk_dag_successors and qk_dag_predecessors, respectively.
This object is read-only from C. To satisfy the safety guarantees of qk_dag_neighbors_clear, you must not overwrite any data initialized by qk_dag_successors or qk_dag_predecessors, including any pointed-to data.
const uint32_t *neighbors
Array of size num_neighbors of node indices.
size_t num_neighbors
The length of the neighbors array.
Functions
qk_dag_new
QkDag *qk_dag_new(void)
Construct a new empty DAG.
You must free the returned DAG with qk_dag_free when done with it.
Example
QkDag *empty = qk_dag_new();Returns
A pointer to the created DAG.
qk_dag_add_quantum_register
void qk_dag_add_quantum_register(QkDag *dag, const QkQuantumRegister *reg)
Add a quantum register to the DAG.
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1024, "my_register");
qk_dag_add_quantum_register(dag, qr);
qk_quantum_register_free(qr);
qk_dag_free(dag);Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag and if reg is not a valid, non-null pointer to a QkQuantumRegister.
Parameters
- dag – A pointer to the DAG.
- reg – A pointer to the quantum register.
qk_dag_add_classical_register
void qk_dag_add_classical_register(QkDag *dag, const QkClassicalRegister *reg)
Add a classical register to the DAG.
Example
QkDag *dag = qk_dag_new();
QkClassicalRegister *cr = qk_classical_register_new(24, "my_register");
qk_dag_add_classical_register(dag, cr);
qk_classical_register_free(cr);
qk_dag_free(dag);Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag and if reg is not a valid, non-null pointer to a QkClassicalRegister.
Parameters
- dag – A pointer to the DAG.
- reg – A pointer to the classical register.
qk_dag_num_qubits
uint32_t qk_dag_num_qubits(const QkDag *dag)
Get the number of qubits the DAG contains.
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(24, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t num_qubits = qk_dag_num_qubits(dag); // num_qubits==24
qk_quantum_register_free(qr);
qk_dag_free(dag);Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
Returns
The number of qubits the DAG is defined on.
qk_dag_num_clbits
uint32_t qk_dag_num_clbits(const QkDag *dag)
Get the number of clbits the DAG contains.
Example
QkDag *dag = qk_dag_new();
QkClassicalRegister *cr = qk_classical_register_new(24, "my_register");
qk_dag_add_classical_register(dag, cr);
uint32_t num_clbits = qk_dag_num_clbits(dag); // num_clbits==24
qk_classical_register_free(cr);
qk_dag_free(dag);Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
Returns
The number of clbits the DAG is defined on.
qk_dag_num_op_nodes
size_t qk_dag_num_op_nodes(const QkDag *dag)
Return the total number of operation nodes in the DAG.
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
size_t num = qk_dag_num_op_nodes(dag); // 1
qk_dag_free(dag);
qk_quantum_register_free(qr);Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
Returns
The total number of instructions in the DAG.
qk_dag_node_type
QkDagNodeType qk_dag_node_type(const QkDag *dag, uint32_t node)
Get the type of the specified node.
The result can be used in a switch statement to dispatch proper handling when iterating over nodes of unknown type.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The node to get the type of.
Returns
The type of the node.
qk_dag_qubit_in_node
uint32_t qk_dag_qubit_in_node(const QkDag *dag, uint32_t qubit)
Retrieve the index of the input node of the wire corresponding to the given qubit.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- qubit – The qubit to get the input node index of.
Returns
The input node of the qubit wire.
qk_dag_qubit_out_node
uint32_t qk_dag_qubit_out_node(const QkDag *dag, uint32_t qubit)
Retrieve the index of the output node of the wire corresponding to the given qubit.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- qubit – The qubit to get the output node index of.
Returns
The output node of the qubit wire.
qk_dag_clbit_in_node
uint32_t qk_dag_clbit_in_node(const QkDag *dag, uint32_t clbit)
Retrieve the index of the input node of the wire corresponding to the given clbit.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- clbit – The clbit to get the input node index of.
Returns
The input node of the clbit wire.
qk_dag_clbit_out_node
uint32_t qk_dag_clbit_out_node(const QkDag *dag, uint32_t clbit)
Retrieve the index of the output node of the wire corresponding to the given clbit.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- clbit – The clbit to get the output node index of.
Returns
The output node of the clbit wire.
qk_dag_wire_node_value
uint32_t qk_dag_wire_node_value(const QkDag *dag, uint32_t node)
Retrieve the value of a wire endpoint node.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The endpoint node to get the wire value of.
Returns
The value (e.g. qubit, clbit, or var) within the endpoint node.
qk_dag_op_node_num_qubits
uint32_t qk_dag_op_node_num_qubits(const QkDag *dag, uint32_t node)
Gets the number of qubits of the specified operation node.
Panics if the node is not an operation.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The operation node to get the number of qubits of.
Returns
The number of qubits of the operation.
qk_dag_op_node_num_clbits
uint32_t qk_dag_op_node_num_clbits(const QkDag *dag, uint32_t node)
Gets the number of clbits of the specified operation node.
Panics if the node is not an operation.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The operation node to get the number of clbits of.
Returns
The number of clbits of the operation.
qk_dag_op_node_num_params
uint32_t qk_dag_op_node_num_params(const QkDag *dag, uint32_t node)
Gets the number of params of the specified operation node.
Panics if the node is not an operation.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The operation node to get the number of params of.
Returns
The number of params of the operation.
qk_dag_op_node_qubits
const uint32_t *qk_dag_op_node_qubits(const QkDag *dag, uint32_t node)
Retrieve the qubits of the specified operation node.
Panics if the node is not an operation.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The operation node to get the qubits of.
Returns
A pointer to the qubits. Use qk_dag_op_node_num_qubits to determine the number of elements.
qk_dag_op_node_clbits
const uint32_t *qk_dag_op_node_clbits(const QkDag *dag, uint32_t node)
Retrieve the clbits of the specified operation node.
Panics if the node is not an operation.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The operation node to get the clbits of.
Returns
A pointer to the clbits. Use qk_dag_op_node_num_clbits to determine the number of elements.
qk_dag_apply_gate
uint32_t qk_dag_apply_gate(QkDag *dag, QkGate gate, const uint32_t *qubits, const double *params, bool front)
Apply a QkGate to the DAG.
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
qk_dag_free(dag);
qk_quantum_register_free(qr);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 dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG to apply the gate to.
- gate – The StandardGate to apply.
- qubits – The pointer to the array of
uint32_tqubit indices to add the gate on. This can be a null pointer if there are no qubits forgate(e.g.QkGate_GlobalPhase). - params – The pointer to the array of
doublevalues to use for the gate parameters. This can be a null pointer if there are no parameters forgate(e.g.QkGate_H). - front – If
true, the gate is applied as the first operation on the specified qubits, rather than as the last.
Returns
The index of the newly added operation node.
qk_dag_apply_measure
uint32_t qk_dag_apply_measure(QkDag *dag, uint32_t qubit, uint32_t clbit, bool front)
Apply a measure to a DAG.
Example
Measure all qubits into the corresponding clbit index at the end of the circuit.
uint32_t num_qubits = qk_dag_num_qubits(dag);
for (uint32_t i = 0; i < num_qubits; i++) {
qk_dag_apply_measure(dag, i, i, false);
}Safety
Behavior is undefined if dag is not an aligned, non-null pointer to a valid QkDag, or if qubit or clbit are out of range.
Parameters
- dag – The circuit to apply to.
- qubit – The qubit index to measure.
- clbit – The clbit index to store the result in.
- front – Whether to apply the measure at the start of the circuit. Usually
false.
Returns
The node index of the created instruction.
qk_dag_apply_reset
uint32_t qk_dag_apply_reset(QkDag *dag, uint32_t qubit, bool front)
Apply a reset to the DAG.
Examples
Apply initial resets on all qubits.
uint32_t num_qubits = qk_dag_num_qubits(dag);
for (uint32_t qubit = 0; qubit < num_qubits; qubit++) {
qk_dag_apply_reset(dag, qubit, true);
}Safety
Behavior is undefined if dag is not an aligned, non-null pointer to a valid QkDag, or if qubit is out of range.
Parameters
- dag – The circuit to apply to.
- qubit – The qubit index to reset.
- front – Whether to apply the reset at the start of the circuit. Usually
false.
Returns
The node index of the created instruction.
qk_dag_apply_barrier
uint32_t qk_dag_apply_barrier(QkDag *dag, const uint32_t *qubits, uint32_t num_qubits, bool front)
Apply a barrier to the DAG.
Examples
Apply a final barrier on all qubits:
qk_dag_apply_barrier(dag, NULL, qk_dag_num_qubits(dag), false);Apply a barrier at the beginning of a circuit on specified qubit indices:
uint32_t qubits[] = {0, 2, 4, 5};
uint32_t num_qubits = sizeof(qubits) / sizeof(qubits[0]);
qk_dag_apply_barrier(dag, qubits, num_qubits, true);Safety
Behavior is undefined if:
dagis not an aligned, non-null pointer to a validQkDag,qubitsis not aligned or is not valid fornum_qubitsreads of initialized, in-bounds and unduplicated indices, unlessqubitsis null.
Parameters
- dag – The circuit to apply to.
- qubits – The qubit indices to apply the barrier to. This can be null, in which case
num_qubitsis not read, and the barrier is applied to all qubits in the DAG. - num_qubits – How many qubits the barrier applies to.
- front – Whether to apply the barrier at the start of the circuit. Usually
false.
Returns
The node index of the created instruction.
qk_dag_apply_unitary
uint32_t qk_dag_apply_unitary(QkDag *dag, const QkComplex64 *matrix, const uint32_t *qubits, uint32_t num_qubits, bool front)
Apply a unitary gate to a DAG.
The values in matrix should form a row-major unitary matrix of the correct size for the number of qubits. The data is copied out of the pointer, and only needs to be valid for reads until this function returns.
See :Circuit conventions for detail on the bit-labelling and matrix conventions of Qiskit.
Safety
Behavior is undefined if any of:
dagis not an aligned, non-null pointer to a validQkDag,matrixis not an aligned pointer to4**num_qubitsinitialized values,qubitsis not an aligned pointer tonum_qubitsinitialized values.
Parameters
- dag – The circuit to apply to.
- matrix – An initialized row-major unitary matrix of total size
4**num_qubits. - qubits – An array of distinct
uint32_tindices of the qubits. - num_qubits – The number of qubits the gate applies to.
- front – Whether to apply the gate at the start of the circuit. Usually
false.
Returns
The node index of the created instruction.
qk_dag_op_node_gate_op
QkGate qk_dag_op_node_gate_op(const QkDag *dag, uint32_t node, double *out_params)
Retrieve the standard gate of the specified node.
Panics if the node is not a standard gate operation.
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
uint32_t h_gate_idx = qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
QkGate gate = qk_dag_op_node_gate_op(dag, h_gate_idx, NULL);
qk_dag_free(dag);
qk_quantum_register_free(qr);Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag. If out_params is non-NULL, it must point to a buffer large enough to hold all the gate’s params, otherwise behavior is undefined as this function will write beyond its bounds. You can check qk_dag_op_node_num_params to determine how many params are required for any given operation node.
Parameters
- dag – A pointer to the DAG.
- node – The operation node to get the standard gate of.
- out_params – A buffer to be filled with the gate’s params or NULL if they’re not wanted.
Returns
The gate value.
qk_dag_op_node_unitary
void qk_dag_op_node_unitary(const QkDag *dag, uint32_t node, QkComplex64 *out)
Copy out the unitary matrix of the corresponding node index.
Panics if the node is not a unitary gate.
Safety
Behavior is undefined if dag is not a non-null pointer to a valid QkDag, if out is unaligned, or if out is not valid for 4**num_qubits writes of QkComplex64.
Parameters
- dag – The circuit to read from.
- node – The node index of the unitary matrix instruction.
- out – Allocated and aligned memory for
4**num_qubitscomplex values in row-major order, wherenum_qubitsis the number of qubits the gate applies to.
qk_dag_op_node_kind
QkOperationKind qk_dag_op_node_kind(const QkDag *dag, uint32_t node)
Get the “kind” of an operation node.
The result can be used in a switch statement to dispatch proper handling when iterating over operation nodes.
Panics if node is not an operation node.
Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The operation node to get the “kind” of.
Returns
The “kind” of the node.
qk_dag_successors
QkDagNeighbors qk_dag_successors(const QkDag *dag, uint32_t node)
Retrieve the successors of the specified node.
The successors array and its length are returned as a QkDagNeighbors struct, where each element in the array corresponds to a DAG node index. You must call the qk_dag_neighbors_clear function when done to free the memory allocated for the struct.
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
qk_quantum_register_free(qr);
uint32_t node_cx = qk_dag_apply_gate(dag, QkGate_CX, (uint32_t[]){0, 1}, NULL, false);
QkDagNeighbors successors = qk_dag_successors(dag, node_cx);
qk_dag_neighbors_clear(&successors);
qk_dag_free(dag);Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The node to get the successors of.
Returns
An instance of the QkDagNeighbors struct with the successors information.
qk_dag_predecessors
QkDagNeighbors qk_dag_predecessors(const QkDag *dag, uint32_t node)
Retrieve the predecessors of the specified node.
The predecessors array and its length are returned as a QkDagNeighbors struct, where each element in the array corresponds to a DAG node index. You must call the qk_dag_neighbors_clear function when done to free the memory allocated for the struct.
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
qk_quantum_register_free(qr);
uint32_t node_cx = qk_dag_apply_gate(dag, QkGate_CX, (uint32_t[]){0, 1}, NULL, false);
QkDagNeighbors predecessors = qk_dag_predecessors(dag, node_cx);
qk_dag_neighbors_clear(&predecessors);
qk_dag_free(dag);Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The node to get the predecessors of.
Returns
An instance of the QkDagNeighbors struct with the predecessors information.
qk_dag_neighbors_clear
void qk_dag_neighbors_clear(QkDagNeighbors *neighbors)
Clear the fields of the input QkDagNeighbors struct.
The function deallocates the memory pointed to by the neighbors field and sets it to NULL. It also sets the num_neighbors field to 0.
Safety
Behavior is undefined if neighbors is not a valid, non-null pointer to a QkDagNeighbors object populated with either qk_dag_successors or qk_dag_predecessors.
Parameters
- neighbors – A pointer to a
QkDagNeighborsobject.
qk_dag_get_instruction
void qk_dag_get_instruction(const QkDag *dag, uint32_t index, QkCircuitInstruction *instruction)
Return the details for an instruction in the circuit.
This is a mirror of qk_circuit_get_instruction. You can also use individual methods such as qk_dag_op_node_gate_op to get individual properties.
You must call qk_circuit_instruction_clear to reset the QkCircuitInstruction before reusing it or dropping it.
Examples
Iterate through a DAG to find which qubits have measures on them:
bool *measured = calloc(qk_dag_num_qubits(dag), sizeof(*measured));
uint32_t num_ops = qk_dag_num_op_nodes(dag);
uint32_t *ops = malloc(num_ops * sizeof(*ops));
qk_dag_topological_op_nodes(dag, ops);
// Storage space for the instruction.
QkCircuitInstruction inst;
for (uint32_t i = 0; i < num_ops; i++) {
qk_dag_get_instruction(dag, ops[i], &inst);
if (!strcmp(inst.name, "measure"))
measured[inst.qubits[0]] = true;
qk_circuit_instruction_clear(&inst);
}
free(ops);
free(measured);Safety
Behavior is undefined if either dag or instruction are not valid, aligned, non-null pointers to the relevant data type. The fields of instruction need not be initialized.
Parameters
- dag – The circuit to retrieve the instruction from.
- index – The node index. It is an error to pass an index that is node a valid op node.
- instruction – A point to where to write out the
QkCircuitInstruction.
qk_dag_compose
QkExitCode qk_dag_compose(QkDag *dag, const QkDag *other, const uint32_t *qubits, const uint32_t *clbits)
Compose the other DAG onto the dag instance with the option of a subset of input wires of other being mapped onto a subset of output wires of dag.
other may include a smaller or equal number of wires for each type.
Example
// Build the following dag
// rqr_0: ──■───────
// │ ┌───┐
// rqr_1: ──┼──┤ Y ├
// ┌─┴─┐└───┘
// rqr_2: ┤ X ├─────
// └───┘
QkDag *dag_right = qk_dag_new();
QkQuantumRegister *rqr = qk_quantum_register_new(3, "rqr");
qk_dag_add_quantum_register(dag_right, rqr);
qk_dag_add_classical_register(dag_right, rcr);
qk_dag_apply_gate(dag_right, QkGate_CX, (uint32_t[]){0, 2}, NULL, false);
qk_dag_apply_gate(dag_right, QkGate_Y, (uint32_t[]){1}, NULL, false);
// Build the following dag
// ┌───┐
// lqr_0: ──┤ H ├───
// ┌─┴───┴──┐
// lqr_1: ┤ P(0.1) ├
// └────────┘
QkDag *dag_left = qk_dag_new();
QkQuantumRegister *lqr = qk_quantum_register_new(2, "lqr");
qk_dag_add_quantum_register(dag_left, lqr);
qk_dag_add_classical_register(dag_left, lcr);
qk_dag_apply_gate(dag_left, QkGate_H, (uint32_t[]){0}, NULL, false);
qk_dag_apply_gate(dag_left, QkGate_Phase, (uint32_t[]){1}, (double[]){0.1}, false);
// Compose left circuit onto right circuit
// Should result in circuit
// ┌───┐
// rqr_0: ──■──┤ H ├──────────
// │ ├───┤┌────────┐
// rqr_1: ──┼──┤ Y ├┤ P(0.1) ├
// ┌─┴─┐└───┘└────────┘
// rqr_2: ┤ X ├───────────────
// └───┘
qk_dag_compose(dag_right, dag_left, NULL, NULL);
// Clean up after you're done
qk_dag_free(dag_left);
qk_dag_free(dag_right);
qk_quantum_register_free(lqr);
qk_quantum_register_free(rqr);Safety
Behavior is undefined if dag or other are not valid, non-null pointers to a QkDag. If qubit nor clbit are NULL, it must contains a less or equal amount than what the circuit owns.
Parameters
- dag – A pointer to the DAG to be composed on.
- other – A pointer to the DAG to compose with
dag. - qubits – A list of indices representing the qubit wires to compose onto.
- clbits – A list of indices representing the clbit wires to compose onto.
Returns
QkExitCode_Success upon successful decomposition, otherwise a DAG-specific error code indicating the cause of the failure.
qk_dag_free
void qk_dag_free(QkDag *dag)
Free the DAG.
Example
QkDag *dag = qk_dag_new();
qk_dag_free(dag);Safety
Behavior is undefined if dag is not either null or a valid pointer to a QkDag.
Parameters
- dag – A pointer to the DAG to free.
qk_dag_to_circuit
QkCircuit *qk_dag_to_circuit(const QkDag *dag)
Convert a given DAG to a circuit.
The new circuit is copied from the DAG; the original dag reference is still owned by the caller and still required to be freed with qk_dag_free. You must free the returned circuit with qk_circuit_free when done with it.
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
qk_quantum_register_free(qr);
QkCircuit *qc = qk_dag_to_circuit(dag);
qk_circuit_free(qc);
qk_dag_free(dag);Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG from which to create the circuit.
Returns
A pointer to the new circuit.
qk_dag_topological_op_nodes
void qk_dag_topological_op_nodes(const QkDag *dag, uint32_t *out_order)
Return the operation nodes in the DAG listed in topological order.
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
qk_dag_apply_gate(dag, QkGate_S, qubit, NULL, false);
// get the number of operation nodes
uint32_t num_ops = qk_dag_num_op_nodes(dag); // 2
uint32_t *out_order = malloc(sizeof(uint32_t) * num_ops);
// get operation nodes listed in topological order
qk_dag_topological_op_nodes(dag, out_order);
// do something with the ordered nodes
for (uint32_t i = 0; i < num_ops; i++) {
QkGate gate = qk_dag_op_node_gate_op(dag, out_order[i], NULL);
printf("The gate at location %u is %u.\n", i, gate);
}
// free the out_order array, register, and dag pointer when done
free(out_order);
qk_quantum_register_free(qr);
qk_dag_free(dag);Safety
Behavior is undefined if dag is not a valid, non-null pointer to a QkDag or if out_order is not a valid, non-null pointer to a sequence of qk_dag_num_op_nodes(dag) consecutive elements of uint32_t.
Parameters
- dag – A pointer to the DAG.
- out_order – A pointer to an array of
qk_dag_num_op_nodes(dag)elements of typeuint32_t, where this function will write the output to.
qk_dag_substitute_node_with_dag
void qk_dag_substitute_node_with_dag(QkDag *dag, uint32_t node, const QkDag *replacement)
Replace a node in a QkDag with a subcircuit specfied by another QkDag
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
uint32_t node_to_replace = qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
qk_dag_apply_gate(dag, QkGate_S, qubit, NULL, false);
// Build replacement dag for H
QkDag *replacement = qk_dag_new();
QkQuantumRegister *replacement_qr = qk_quantum_register_new(1, "other");
qk_dag_add_quantum_register(replacement, replacement_qr);
double pi_param[1] = {3.14159};
qk_dag_apply_gate(replacement, QkGate_RZ, qubit, pi_param, false);
qk_dag_apply_gate(replacement, QkGate_SX, qubit, NULL, false);
qk_dag_apply_gate(replacement, QkGate_RZ, qubit, pi_param, false);
qk_dag_substitute_node_with_dag(dag, node_to_replace, replacement);
// Free the replacement dag, register, dag, and register
qk_quantum_register_free(replacement_qr);
qk_dag_free(replacement);
qk_quantum_register_free(qr);
qk_dag_free(dag);Safety
Behavior is undefined if dag and replacement are not a valid, non-null pointer to a QkDag.
Parameters
- dag – A pointer to the DAG.
- node – The node index of the operation to replace with the other
QkDag. This must be the node index for an operation node indagand the qargs and cargs count must match the number of qubits and clbits inreplacement. - replacement – The other
QkDagto replacenodewith. This dag must have the same number of qubits as the operation fornode. The node bit ordering will be ordering will be handled in order, soqargs[0]fornodewill be mapped toqubits[0]inreplacement,qargs[1]toqubits[0], etc. The same pattern applies to classical bits too.
qk_dag_copy_empty_like
QkDag *qk_dag_copy_empty_like(const QkDag *dag, QkVarsMode vars_mode, QkBlocksMode blocks_mode)
Return a copy of self with the same structure but empty.
That structure includes:
- name and other metadata
- global phase
- duration
- all the qubits and clbits, including the registers.
Example
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(1, "my_register");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {0};
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
// As the DAG does not contain any control-flow instructions,
// vars_mode and blocks_mode do not have any effect.
QkDag *copied_dag = qk_dag_copy_empty_like(dag, QkVarsMode_Alike, QkBlocksMode_Drop);
uint32_t num_ops_in_copied_dag = qk_dag_num_op_nodes(copied_dag); // 0
// do something with copied_dag
qk_quantum_register_free(qr);
qk_dag_free(dag);
qk_dag_free(copied_dag);Safety
Behavior is undefined if dag is not a valid pointer to a QkDag.
Parameters
- dag – A pointer to the DAG to copy.
- vars_mode – The mode for handling classical variables.
- blocks_mode – The mode for handling blocks.
Returns
The pointer to the copied DAG circuit.