# Is there a way to decompose a quantum circuit into layers?

For example, if take the following circuit as the input (either QASM or Qiskit):

qreg q[2];
creg c[2];

x q[1];
h q[0];
h q[1];
cx q[0],q[1];
h q[0];
measure q[0] -> c[0];
measure q[1] -> c[1];


The expected output will be:

layer[0] = [H [q0], X [q1]]
layer[1] = [H [q1]]
layer[2] = [cnot [q0] [q1]]
layer[3] = [H [q0]]
layer[4] = [measure [q0]]
layer[5] = [measure [q1]]


Is there a Qiskit function to achieve this? If not, suggestions to implement this task are also welcomed.

Thanks!

• The issue is that the decomposition is not unique. Layers 0 and 1 can be either those you mentioned or layer[0] = [X [q1]] and layer[1] = [H [q0], H [q1]]. Also note that you should put identity operators to empty places in the circuit, i.e. your layer 1 should be layer[1] = [I q[0], H [q1]] Oct 17, 2022 at 18:01
• @MartinVesely Thanks! Yes that's a great point. I guess only CNOT will clearly divide different layers between a bunch of single-qubit gates.
– Mao
Oct 18, 2022 at 5:04
• Yes, or any controlled or multi-controlled gate. Oct 18, 2022 at 6:26
• Just one note. Imagine that you have several controlled gates in row and one single-qubit gate on a qubit below the controlled gates, then it is also ambiguous under which controlled gate to place the single-qubit one. Oct 18, 2022 at 8:54
• That is also true, seems like I need to define some scheduling policy first...
– Mao
Oct 19, 2022 at 1:28

You can decompose a quantum circuit into layers using DAGCircuit.layers() method:

from qiskit.converters import circuit_to_dag, dag_to_circuit
from IPython.display import display

dag = circuit_to_dag(circ)
for layer in dag.layers():
layer_as_circuit = dag_to_circuit(layer['graph'])
display(layer_as_circuit.draw('mpl'))


where circ is a QuantumCircuit. The output will be:

DAGCircuit.layers() method constructs the layers using a greedy algorithm.

You can also break down your circuit into layers based on some scheduling policy. In the following example we apply an "as late as possible" (ALAP) scheduling policy:

from qiskit.transpiler import PassManager, InstructionDurations
from qiskit.transpiler.passes import  ALAPScheduleAnalysis, PadDelay

# Apply the scheduling policy:
instruction_durations = InstructionDurations(
[
("h", None, 160),
("x", None, 160),
("cx", None, 800),
("measure", None, 1600),
]
)

pass_manager = PassManager(
[
ALAPScheduleAnalysis(instruction_durations),
]
)
transpiled_circ = pass_manager.run(circ)

# Use DAGCircuit.layers() method with the transpiled circuit:
dag = circuit_to_dag(transpiled_circ)
for layer in dag.layers():
layer_as_circuit = dag_to_circuit(layer['graph'])
# Remove the Delay instructions:
for _inst in layer_as_circuit.data:
if _inst.operation.name == 'delay':
layer_as_circuit.data.remove(_inst)

display(layer_as_circuit.draw('mpl'))


The result:

Similarly, you can apply "as soon as possible" (ASAP) scheduling policy.