---
title: QkDag (latest version)
description: API reference for QkDag in the latest version of qiskit-c
source: https://quantum.cloud.ibm.com/docs/en/api/qiskit-c/qk-dag
---

# QkDag

```c
typedef struct QkDag QkDag
```

The `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`](/docs/api/qiskit/qiskit.dagcircuit.DAGCircuit#qiskit.dagcircuit.DAGCircuit "qiskit.dagcircuit.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`](/docs/api/qiskit/circuit#qiskit.circuit.Barrier "qiskit.circuit.Barrier"), [`Measure`](/docs/api/qiskit/circuit#qiskit.circuit.Measure "qiskit.circuit.Measure"), [`Reset`](/docs/api/qiskit/circuit#qiskit.circuit.Reset "qiskit.circuit.Reset"), and [`Delay`](/docs/api/qiskit/circuit#qiskit.circuit.Delay "qiskit.circuit.Delay")) and [`UnitaryGate`](/docs/api/qiskit/qiskit.circuit.library.UnitaryGate#qiskit.circuit.library.UnitaryGate "qiskit.circuit.library.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.

#### enumerator QkOperationKind\_PauliProductRotation

### 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

```c
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

```c
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

```c
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

```c
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

```c
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

```c
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\_global\_phase

`QkParam *qk_dag_global_phase(const QkDag *dag)`

Get the global phase of the DAG.

This function returns a copy of the DAG’s global phase and the value must be freed via :c:func:`qk_param_free` after usage.

#### Example

```c
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(24, "my_register");
qk_dag_add_quantum_register(dag, qr);
QkParam *global_phase = qk_dag_global_phase(dag);
qk_param_free(global_phase);
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 global phase of the DAG.

### qk\_dag\_set\_global\_phase

`QkExitCode qk_dag_set_global_phase(QkDag *dag, const QkParam *phase)`

Set the global phase of the DAG.

This function copies the new global phase upon setting it, so the caller retains ownership of the `QkParam` phase, and the value of the phase must be freed via :c:func:`qk_param_free` after setting.

#### Example

```c
QkDag *dag = qk_dag_new();
QkParam *new_global_phase = qk_param_from_double(1.23);
qk_dag_set_global_phase(dag, new_global_phase);
qk_param_free(new_global_phase);
qk_dag_free(dag);
```

#### Safety

Behavior is undefined if `dag` is not a valid, non-null pointer to a `QkDag` and if `phase` is not a valid, non-null pointer to a `QkParam`.

**Parameters**

- **dag** – A pointer to the DAG.
- **phase** – A pointer to the global phase to set.

**Returns**

`QkExitCode_Success` upon successful setting of the global phase. Upon failure, `QkExitCode_ParameterError` describes generic failures when attempting to track the parameter symbols such as invalid parameter values. Otherwise, `QkExitCode_DagError` indicates a DAG-specific cause of the failure.

### 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

```c
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_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`).
- **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.

```c
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.

```c
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:

```c
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:

```c
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:

- `dag` is not an aligned, non-null pointer to a valid `QkDag`,
- `qubits` is not aligned or is not valid for `num_qubits` reads of initialized, in-bounds and unduplicated indices, unless `qubits` is 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_qubits` is 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](/docs/api/qiskit/circuit#circuit-conventions) for detail on the bit-labelling and matrix conventions of Qiskit.

#### Safety

Behavior is undefined if any of:

- `dag` is not an aligned, non-null pointer to a valid `QkDag`,
- `matrix` is not an aligned pointer to `4**num_qubits` initialized values,
- `qubits` is not an aligned pointer to `num_qubits` initialized 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_t` indices 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

```c
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_qubits` complex values in row-major order, where `num_qubits` is 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

```c
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

```c
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](#structqkdagneighbors) object populated with either `qk_dag_successors` or `qk_dag_predecessors`.

**Parameters**

- **neighbors** – A pointer to a `QkDagNeighbors` object.

### 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:

```c
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

```c
// 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

```c
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

```c
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

```c
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 type `uint32_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 specified by another `QkDag`

#### Example

```c
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 in `dag` and the qargs and cargs count must match the number of qubits and clbits in `replacement`.
- **replacement** – The other `QkDag` to replace `node` with. This dag must have the same number of qubits as the operation for `node`. The node bit ordering will be ordering will be handled in order, so `qargs[0]` for `node` will be mapped to `qubits[0]` in `replacement`, `qargs[1]` to `qubits[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

```c
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.

### qk\_dag\_replace\_block\_with\_unitary

`uint32_t qk_dag_replace_block_with_unitary(QkDag *dag, uint32_t num_block_ids, const uint32_t *block_ids, const QkComplex64 *matrix, uint32_t num_qubits, const uint32_t *qubits, bool cycle_check)`

Replace a non-empty contiguous block of nodes in a `QkDag` with a single unitary gate corresponding to the specified unitary matrix.

Upon replacement, the nodes in the block are removed and substituted by a new node acting on the given qubits.

#### Example

```c
// Create a DAG with H, T, S, T, H gates on the second qubit
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
uint32_t qubit[1] = {1};
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);
uint32_t idx1 = qk_dag_apply_gate(dag, QkGate_T, qubit, NULL, false);
uint32_t idx2 = qk_dag_apply_gate(dag, QkGate_S, qubit, NULL, false);
uint32_t idx3 = qk_dag_apply_gate(dag, QkGate_T, qubit, NULL, false);
qk_dag_apply_gate(dag, QkGate_H, qubit, NULL, false);

// Replace the inner T, S, T gates by a unitary gate (representing Z)
uint32_t replaced_ids[3] = {idx1, idx2, idx3};
static const QkComplex64 mat_z[4] = {{1, 0}, {0, 0}, {0, 0}, {-1, 0}};
uint32_t new_node_idx =
    qk_dag_replace_block_with_unitary(dag, 3, replaced_ids, mat_z, 1, qubit, false);

// free the register and dag pointer when done
qk_quantum_register_free(qr);
qk_dag_free(dag);
```

#### Safety

Behavior is undefined if any of:

- `dag` is not an aligned, non-null pointer to a valid `QkDag`,
- `qubits` is not an aligned pointer to `num_qubits` initialized values.
- `matrix` is not an aligned pointer to `4**num_qubits` initialized values,
- `block_ids` is not an aligned pointer to `num_block_ids` initialized values.

**Parameters**

- **dag** – Pointer to the DAG.
- **num\_block\_ids** – Number of entries in `block_ids`. This number must be nonzero.
- **block\_ids** – Pointer to a non-empty array of nodes to replace.
- **matrix** – Pointer to an initialized row-major unitary matrix of size `4**num_qubits`.
- **num\_qubits** – The number of qubits the resulting unitary gate acts on.
- **qubits** – Pointer to an array of distinct `uint32_t` qubit indices. Each entry specifies the index of the DAG qubit that corresponds to the respective argument position in the unitary gate.
- **cycle\_check** – If `true`, the function checks whether replacing the provided `block_ids` with a single node would introduce a cycle in the DAG (which would invalidate the DAG). If a cycle would be created, the DAG is left unchanged and `UINT32_MAX` is returned. This checking comes with a run time penalty. If you can guarantee that the provided `block_ids` is a contiguous block and won’t introduce a cycle when contracted to a single node, this can be set to `false`.

**Returns**

The index of the newly added operation node, or `UINT32_MAX` if `cycle_check` is `true` and the replacement would introduce a cycle.

### qk\_dag\_substitute\_node\_with\_unitary

`void qk_dag_substitute_node_with_unitary(QkDag *dag, uint32_t node, const QkComplex64 *matrix, uint32_t num_qubits)`

Substitute an operation in a node in a `QkDag` with a unitary gate corresponding to the specified unitary matrix.

The new operation should match the shape of the replaced operation. The qargs and cargs for the node will remain the same.

#### Example

```c
// Create a DAG with a Z-gate
QkDag *dag = qk_dag_new();
QkQuantumRegister *qr = qk_quantum_register_new(2, "qr");
qk_dag_add_quantum_register(dag, qr);
uint32_t idx_z = qk_dag_apply_gate(dag, QkGate_Z, (uint32_t[]){1}, NULL, false);

static const QkComplex64 mat[4] = {{1, 0}, {0, 0}, {0, 0}, {-1, 0}};

// Replace the Z-gate by a unitary matrix
qk_dag_substitute_node_with_unitary(dag, idx_z, mat, 1);

// free the register and dag pointer when done
qk_quantum_register_free(qr);
qk_dag_free(dag);
```

#### Safety

Behavior is undefined if any of:

- `dag` is not an aligned, non-null pointer to a valid `QkDag`,
- `matrix` is not an aligned pointer to `4**num_qubits` initialized values,

**Parameters**

- **dag** – Pointer to the DAG.
- **node** – The node whose operation is substituted. The number of qubits in the substituted operation should equal to `num_qubits` and the number of clbits should be `0`.
- **matrix** – Pointer to an initialized row-major unitary matrix of size `4**num_qubits`.
- **num\_qubits** – The number of qubits the unitary acts on.

### qk\_dag\_to\_python

`PyObject *qk_dag_to_python(QkDag *dag)`

Pass ownership of a `QkDag` object to Python.

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

#### Safety

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

**Parameters**

- **dag** – The owned object.

**Returns**

An owned Python reference to the object.

### qk\_dag\_borrow\_from\_python

`QkDag *qk_dag_borrow_from_python(PyObject *ob)`

Retrieve a `QkDag` pointer from a Python object.

This borrows a Python reference and extracts the `QkDag` 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_dag_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\_dag\_convert\_from\_python

`int qk_dag_convert_from_python(PyObject *object, void *address)`

Retrieve a DAG pointer from a Python object.

This borrows a Python reference and extracts the `QkDag` 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 1, 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_dag_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.
