decompose#

decompose(level: int | float = inf, decompose_predicate: Callable[[Operation], bool] | None = None, collect_gphases: bool = False) Callable[[QuantumCircuit], QuantumCircuit][source]#

Create a pass that recursively decomposes synthesized gates.

Every gate that has a .definition (a sub-circuit) is dissolved into its constituent elementary gates up to the specified recursion level. Gates whose definitions themselves contain further synthesized gates are expanded deeper with each level increment.

By default level is np.inf, so all synthesized gates are decomposed all the way down to elementary gates in a single pass.

Parameters:
levelint or float, optional

Maximum recursion depth for decomposition. 0 leaves the circuit unchanged. 1 dissolves one layer of synthesized gates. Higher values expand deeper nested definitions. The default is np.inf, which decomposes all synthesized gates down to elementary gates.

decompose_predicateCallable[[Operation], bool], optional

An optional predicate function that receives each Operation as its only argument and returns True if the gate should be decomposed. Gates for which the predicate returns False are left intact even if they have a .definition and are within the recursion level. When None (the default), all synthesized gates are decomposed.

collect_gphasesbool, optional

If True, all GPhaseGate instructions in the decomposed circuit are removed and their phases accumulated into a single gphase gate appended to the first qubit of the last non-trivial instruction (one with num_qubits > 0). This ensures the global phase gate does not act on a freshly allocated qubit, avoiding interference with qubit-freshness mechanisms. Default is False.

Returns:
Callable[[QuantumCircuit], QuantumCircuit]

A pass function suitable for PassManager.add_pass() or PassManager.__iadd__().

Examples

Decompose an MCX gate down to elementary gates:

>>> from qrisp import QuantumCircuit, PassManager
>>> from qrisp import decompose
>>> qc = QuantumCircuit(3)
>>> qc.mcx([0, 1], 2)
>>> print(qc)
qb_71: ──■──

qb_72: ──■──
       ┌─┴─┐
qb_73: ┤ X ├
       └───┘

>>> pm = PassManager()
>>> pm += decompose()
>>> decomposed_qc = pm.run(qc)
>>> print(decomposed_qc)
       ┌─────┐
qb_71: ┤ Tdg ├───────■─────────■────■───────────────────────■──
       ├─────┤┌───┐  │  ┌───┐┌─┴─┐  │  ┌─────┐┌───┐ ┌───┐ ┌─┴─┐
qb_72: ┤ Tdg ├┤ X ├──┼──┤ T ├┤ X ├──┼──┤ Tdg ├┤ X ├─┤ T ├─┤ X ├
       └┬───┬┘└─┬─┘┌─┴─┐├───┤└───┘┌─┴─┐└─────┘└─┬─┘┌┴───┴┐├───┤
qb_73: ─┤ H ├───■──┤ X ├┤ T ├─────┤ X ├─────────■──┤ Tdg ├┤ H ├
        └───┘      └───┘└───┘     └───┘            └─────┘└───┘

Decompose only specific gates with a predicate:

>>> pm2 = PassManager()
>>> pm2 += decompose(decompose_predicate=lambda op: "cx" in op.name)

Decompose only one layer:

>>> pm3 = PassManager()
>>> pm3 += decompose(level=1)