Skip to main content
IBM Quantum Platform

TwoQubitPeepholeOptimization

class qiskit.transpiler.passes.TwoQubitPeepholeOptimization(*args, **kwargs)

GitHub

Bases: TransformationPass

Unified two qubit unitary peephole optimization

This transpiler pass is designed to perform two qubit unitary peephole optimization. This pass finds all the 2 qubit blocks in the circuit, computes the unitary of that block, and then synthesizes that unitary. If the synthesized two qubit unitary is “better” than the original subcircuit that subcircuit is used to replace the original. The heuristic used to determine if it’s better first looks at the two qubit gate count in the circuit, and prefers the synthesis with fewer two qubit gates, if the two qubit gate counts are the same then it looks at the estimated fidelity of the circuit and picks the subcircuit with higher estimated fidelity, and finally if needed it picks the subcircuit with the fewest total gates.

In case the target is overcomplete the pass will try all the decomposers supported for all the gates supported on a given qubit. The decomposition that has the best expected performance using the above heuristic will be selected and used to replace the block.

This pass is designed to be run on a physical circuit and the details of operations on a given qubit is assumed to be the hardware qubit from the target. However, the output of the pass might not use hardware operations, specifically single qubit gates might be emitted outside the target’s supported operations, typically only if a parameterized gate supported by the TwoQubitControlledUDecomposer is used for synthesis. As such if running this pass in a physical optimization stage (such as Optimization stage) this should be paired with passes such as BasisTranslator and/or Optimize1qGatesDecomposition to ensure that these errant single qubit gates are replaced with hardware supported operations prior to exiting the stage.

This pass is multithreaded, and will perform the analysis in parallel and use all the cores available on your local system. You can refer to the configuration guide for details on how to control the threading behavior for Qiskit more broadly which will also control this pass

This pass is similar in functionality to running ConsolidateBlocks and UnitarySynthesis sequentially in your pass manager. However, this pass offers improved runtime performance by performing the synthesis in parallel. It also has improved heuristics enabled by doing the optimization in a single step which can result in better quality output, especially in cases of overcomplete and/or heterogeneous targets. However, these heuristics and this pass as a whole are only valid for physical circuits. Additionally, unlike UnitarySynthesis pass this does not use Unitary Synthesis Plugins. This is a tradeoff for performance and it forgoes the pluggability exposed via that interface. Internally it currently only uses the TwoQubitBasisDecomposer and TwoQubitControlledUDecomposer for synthesizing the two qubit unitaries. You should not use this pass if you need to use the pluggable interface and the ability to use different synthesis algorithms, instead you should use a combination of ConsolidateBlocks and UnitarySynthesis to leverage the plugin mechanism in UnitarySynthesis.

from qiskit.circuit import QuantumCircuit
from qiskit.transpiler.passes import TwoQubitPeepholeOptimization
from qiskit.providers.fake_provider import GenericBackendV2

# Build an unoptimized 2 qubit circuit
unoptimized = QuantumCircuit(2)
for i in range(10):
  if i % 2:
    unoptimized.cx(0, 1)
  else:
    unoptimized.cx(1, 0)
# Generate a target with random error rates
backend = GenericBackendV2(2, ["u", "cx"], coupling_map=[[0, 1], [1, 0]])
# Instantiate pass
peephole_pass = TwoQubitPeepholeOptimization(backend.target)
# Run pass and visualize output
optimized = peephole_pass(unoptimized)
optimized.draw("mpl")
Optimized circuit

Initialize the pass

Parameters

  • target – The target to run the pass for
  • approximation_degree – heuristic dial used for circuit approximation (1.0=no approximation, 0.0=maximal approximation). Approximation can decrease the number of gates used in the synthesized unitaries smaller at the cost of straying from the original unitary. If None, approximation is done based on gate fidelities specified in the target.

Attributes

is_analysis_pass

Check if the pass is an analysis pass.

If the pass is an AnalysisPass, that means that the pass can analyze the DAG and write the results of that analysis in the property set. Modifications on the DAG are not allowed by this kind of pass.

is_transformation_pass

Check if the pass is a transformation pass.

If the pass is a TransformationPass, that means that the pass can manipulate the DAG, but cannot modify the property set (but it can be read).


Methods

execute

execute(passmanager_ir, state, callback=None)

GitHub

Execute optimization task for input Qiskit IR.

Parameters

  • passmanager_ir (DAGCircuit) – Qiskit IR to optimize.
  • state (DAGCircuit) – State associated with workflow execution by the pass manager itself.
  • callback (Callable[[Task, DAGCircuit, PropertySet, float, int], None] | None) – A callback function which is called per execution of optimization task.

Returns

Optimized Qiskit IR and state of the workflow.

Return type

tuple[DAGCircuit, PassManagerState]

name

name()

GitHub

Name of the pass.

Return type

str

run

run(dag)

GitHub

Run a pass on the DAGCircuit. This is implemented by the pass developer.

Parameters

dag (DAGCircuit) – the dag on which the pass is run.

Raises

NotImplementedError – when this is left unimplemented for a pass.

Return type

DAGCircuit

update_status

update_status(state, run_state)

GitHub

Update workflow status.

Parameters

  • state (PassManagerState) – Pass manager state to update.
  • run_state (RunState) – Completion status of current task.

Returns

Updated pass manager state.

Return type

PassManagerState

Was this page helpful?
Report a bug, typo, or request content on GitHub.