Construct the pairwise-commutation DAG (directed acyclic graph) representation of a quantum circuit.

In the DAG, each node represents a quantum operation, and edges represent non-commutation between two operations.

This transform takes into account that not all operations can be moved next to each other by pairwise commutation.


tape (QNode or QuantumTape or Callable) – The quantum circuit.


The transformed circuit as described in qml.transform. Executing this circuit will provide the commutation DAG.

Return type

qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]


>>> dev = qml.device("default.qubit")
def circuit(x, y, z):
    qml.RX(x, wires=0)
    qml.RX(y, wires=0)
    qml.CNOT(wires=[1, 2])
    qml.RY(y, wires=1)
    qml.CRZ(z, wires=[2, 0])
    qml.RY(-y, wires=1)
    return qml.expval(qml.Z(0))

The commutation dag can be returned by using the following code:

>>> dag_fn = commutation_dag(circuit)
>>> dag = dag_fn(np.pi / 4, np.pi / 3, np.pi / 2)

Nodes in the commutation DAG can be accessed via the get_nodes() method, returning a list of the form (ID, CommutationDAGNode):

>>> nodes = dag.get_nodes()
>>> nodes
NodeDataView({0: <pennylane.transforms.commutation_dag.CommutationDAGNode object at 0x7f461c4bb580>, ...}, data='node')

You can also access specific nodes (of type CommutationDAGNode) by using the get_node() method. See CommutationDAGNode for a list of available node attributes.

>>> second_node = dag.get_node(2)
>>> second_node
<pennylane.transforms.commutation_dag.CommutationDAGNode object at 0x136f8c4c0>
>>> second_node.op
CNOT(wires=[1, 2])
>>> second_node.successors
[3, 4, 5, 6]
>>> second_node.predecessors

For more details, see:

  • Iten, R., Moyard, R., Metger, T., Sutter, D., Woerner, S. “Exact and practical pattern matching for quantum circuit optimization” doi.org/10.1145/3498325


Using PennyLane