diff --git a/qiskit/extensions/quantum_initializer/squ.py b/qiskit/extensions/quantum_initializer/squ.py index 9f3861ebe23e..285ae1b8f22c 100644 --- a/qiskit/extensions/quantum_initializer/squ.py +++ b/qiskit/extensions/quantum_initializer/squ.py @@ -59,7 +59,7 @@ def __init__(self, unitary_matrix, mode="ZYZ", up_to_diagonal=False, u=None): self._diag = None # Create new gate - super().__init__("unitary", 1, [unitary_matrix]) + super().__init__("squ", 1, [unitary_matrix]) def inverse(self): """Return the inverse. diff --git a/qiskit/transpiler/passes/synthesis/unitary_synthesis.py b/qiskit/transpiler/passes/synthesis/unitary_synthesis.py index 2f8739488e10..b4d38d9e3d07 100644 --- a/qiskit/transpiler/passes/synthesis/unitary_synthesis.py +++ b/qiskit/transpiler/passes/synthesis/unitary_synthesis.py @@ -91,6 +91,7 @@ def __init__( natural_direction: Union[bool, None] = None, synth_gates: Union[List[str], None] = None, method: str = "default", + min_qubits: int = None, ): """Synthesize unitaries over some basis gates. @@ -131,11 +132,14 @@ def __init__( ['unitary']. If None and `pulse_optimzie` == True, default to ['unitary', 'swap'] method (str): The unitary synthesis method plugin to use. - + min_qubits: The minimum number of qubits in the unitary to synthesize. If this is set + and the unitary is less than the specified number of qubits it will not be + synthesized. """ super().__init__() self._basis_gates = basis_gates self._approximation_degree = approximation_degree + self._min_qubits = min_qubits self.method = method self.plugins = plugin.UnitarySynthesisPluginManager() self._coupling_map = coupling_map @@ -194,6 +198,8 @@ def run(self, dag: DAGCircuit) -> DAGCircuit: plugin_method._approximation_degree = self._approximation_degree for node in dag.named_nodes(*self._synth_gates): + if self._min_qubits is not None and len(node.qargs) < self._min_qubits: + continue if plugin_method.supports_coupling_map: kwargs["coupling_map"] = ( self._coupling_map, diff --git a/qiskit/transpiler/preset_passmanagers/level0.py b/qiskit/transpiler/preset_passmanagers/level0.py index f598f5d5d8dc..070eb8740031 100644 --- a/qiskit/transpiler/preset_passmanagers/level0.py +++ b/qiskit/transpiler/preset_passmanagers/level0.py @@ -113,12 +113,14 @@ def _choose_layout_condition(property_set): # 3. Decompose so only 1-qubit and 2-qubit gates remain _unroll3q = [ + # Use unitary synthesis for basis aware decomposition of UnitaryGates UnitarySynthesis( basis_gates, approximation_degree=approximation_degree, coupling_map=coupling_map, backend_props=backend_properties, method=unitary_synthesis_method, + min_qubits=3, ), Unroll3qOrMore(), ] @@ -155,9 +157,27 @@ def _swap_condition(property_set): elif translation_method == "translator": from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel - _unroll = [UnrollCustomDefinitions(sel, basis_gates), BasisTranslator(sel, basis_gates)] + _unroll = [ + UnitarySynthesis( + basis_gates, + approximation_degree=approximation_degree, + coupling_map=coupling_map, + backend_props=backend_properties, + method=unitary_synthesis_method, + ), + UnrollCustomDefinitions(sel, basis_gates), + BasisTranslator(sel, basis_gates), + ] elif translation_method == "synthesis": _unroll = [ + UnitarySynthesis( + basis_gates, + approximation_degree=approximation_degree, + coupling_map=coupling_map, + backend_props=backend_properties, + method=unitary_synthesis_method, + min_qubits=3, + ), Unroll3qOrMore(), Collect2qBlocks(), ConsolidateBlocks(basis_gates=basis_gates), diff --git a/qiskit/transpiler/preset_passmanagers/level1.py b/qiskit/transpiler/preset_passmanagers/level1.py index 0cff8a5f5dbd..6483eebffb03 100644 --- a/qiskit/transpiler/preset_passmanagers/level1.py +++ b/qiskit/transpiler/preset_passmanagers/level1.py @@ -133,12 +133,14 @@ def _not_perfect_yet(property_set): # 4. Decompose so only 1-qubit and 2-qubit gates remain _unroll3q = [ + # Use unitary synthesis for basis aware decomposition of UnitaryGates UnitarySynthesis( basis_gates, approximation_degree=approximation_degree, coupling_map=coupling_map, method=unitary_synthesis_method, backend_props=backend_properties, + min_qubits=3, ), Unroll3qOrMore(), ] @@ -175,9 +177,31 @@ def _swap_condition(property_set): elif translation_method == "translator": from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel - _unroll = [UnrollCustomDefinitions(sel, basis_gates), BasisTranslator(sel, basis_gates)] + _unroll = [ + # Use unitary synthesis for basis aware decomposition of UnitaryGates before + # custom unrolling + UnitarySynthesis( + basis_gates, + approximation_degree=approximation_degree, + coupling_map=coupling_map, + method=unitary_synthesis_method, + backend_props=backend_properties, + ), + UnrollCustomDefinitions(sel, basis_gates), + BasisTranslator(sel, basis_gates), + ] elif translation_method == "synthesis": _unroll = [ + # Use unitary synthesis for basis aware decomposition of UnitaryGates before + # collection + UnitarySynthesis( + basis_gates, + approximation_degree=approximation_degree, + coupling_map=coupling_map, + method=unitary_synthesis_method, + backend_props=backend_properties, + min_qubits=3, + ), Unroll3qOrMore(), Collect2qBlocks(), ConsolidateBlocks(basis_gates=basis_gates), diff --git a/qiskit/transpiler/preset_passmanagers/level2.py b/qiskit/transpiler/preset_passmanagers/level2.py index 929e9b270c45..4daf5b1c1d1a 100644 --- a/qiskit/transpiler/preset_passmanagers/level2.py +++ b/qiskit/transpiler/preset_passmanagers/level2.py @@ -167,12 +167,14 @@ def _csp_not_found_match(property_set): # 3. Unroll to 1q or 2q gates _unroll3q = [ + # Use unitary synthesis for basis aware decomposition of UnitaryGates UnitarySynthesis( basis_gates, approximation_degree=approximation_degree, coupling_map=coupling_map, backend_props=backend_properties, method=unitary_synthesis_method, + min_qubits=3, ), Unroll3qOrMore(), ] @@ -209,9 +211,31 @@ def _swap_condition(property_set): elif translation_method == "translator": from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel - _unroll = [UnrollCustomDefinitions(sel, basis_gates), BasisTranslator(sel, basis_gates)] + _unroll = [ + # Use unitary synthesis for basis aware decomposition of UnitaryGates before + # custom unrolling + UnitarySynthesis( + basis_gates, + approximation_degree=approximation_degree, + coupling_map=coupling_map, + backend_props=backend_properties, + method=unitary_synthesis_method, + ), + UnrollCustomDefinitions(sel, basis_gates), + BasisTranslator(sel, basis_gates), + ] elif translation_method == "synthesis": _unroll = [ + # Use unitary synthesis for basis aware decomposition of UnitaryGates before + # collection + UnitarySynthesis( + basis_gates, + approximation_degree=approximation_degree, + coupling_map=coupling_map, + backend_props=backend_properties, + method=unitary_synthesis_method, + min_qubits=3, + ), Unroll3qOrMore(), Collect2qBlocks(), ConsolidateBlocks(basis_gates=basis_gates), diff --git a/qiskit/transpiler/preset_passmanagers/level3.py b/qiskit/transpiler/preset_passmanagers/level3.py index 8f6cecb7be62..1d0c56264239 100644 --- a/qiskit/transpiler/preset_passmanagers/level3.py +++ b/qiskit/transpiler/preset_passmanagers/level3.py @@ -108,12 +108,14 @@ def level_3_pass_manager(pass_manager_config: PassManagerConfig) -> PassManager: # 1. Unroll to 1q or 2q gates _unroll3q = [ + # Use unitary synthesis for basis aware decomposition of UnitaryGates UnitarySynthesis( basis_gates, approximation_degree=approximation_degree, coupling_map=coupling_map, backend_props=backend_properties, method=unitary_synthesis_method, + min_qubits=3, ), Unroll3qOrMore(), ] @@ -212,9 +214,27 @@ def _swap_condition(property_set): elif translation_method == "translator": from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel - _unroll = [UnrollCustomDefinitions(sel, basis_gates), BasisTranslator(sel, basis_gates)] + _unroll = [ + UnitarySynthesis( + basis_gates, + approximation_degree=approximation_degree, + coupling_map=coupling_map, + backend_props=backend_properties, + method=unitary_synthesis_method, + ), + UnrollCustomDefinitions(sel, basis_gates), + BasisTranslator(sel, basis_gates), + ] elif translation_method == "synthesis": _unroll = [ + UnitarySynthesis( + basis_gates, + approximation_degree=approximation_degree, + coupling_map=coupling_map, + backend_props=backend_properties, + method=unitary_synthesis_method, + min_qubits=3, + ), Unroll3qOrMore(), Collect2qBlocks(), ConsolidateBlocks(basis_gates=basis_gates), diff --git a/releasenotes/notes/squ-gate-name-785b7896300a92ef.yaml b/releasenotes/notes/squ-gate-name-785b7896300a92ef.yaml new file mode 100644 index 000000000000..2b0e6fda182a --- /dev/null +++ b/releasenotes/notes/squ-gate-name-785b7896300a92ef.yaml @@ -0,0 +1,18 @@ +--- +features: + - | + The :class:`~qiskit.transpiler.passes.UnitarySynthesis` transpiler pass in + :mod:`qiskit.transpiler.passes` has a new kwarg in the constructor, + ``min_qubits``. When specified this can be set to an ``int`` value which + is the minimum size :class:`~qiskit.extensions.UnitaryGate` object to + run the unitary synthesis on. If a :class:`~qiskit.extensions.UnitaryGate` + in a :class:`~qiskit.circuit.QuantumCircuit` uses fewer qubits it will + be skipped by that instance of the pass. +upgrade: + - | + The :attr:`~qiskit.extensions.SingleQubitUnitary.name` attribute of the + :class:`~qiskit.extensions.SingleQubitUnitary` gate class has been changed + from ``unitary`` to ``squ``. This was necessary to avoid a conflict with + the :class:`~qiskit.extensions.UnitaryGate` class's name which was also + ``unitary`` since the 2 gates are not the same and don't have the same + implementation (and can't be used interchangeably).