Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add min_qubits kwarg to UnitarySynthesis pass #6349

Merged
merged 9 commits into from
Sep 30, 2021
2 changes: 1 addition & 1 deletion qiskit/extensions/quantum_initializer/squ.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 7 additions & 1 deletion qiskit/transpiler/passes/synthesis/unitary_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
22 changes: 21 additions & 1 deletion qiskit/transpiler/preset_passmanagers/level0.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
]
Expand Down Expand Up @@ -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),
Expand Down
26 changes: 25 additions & 1 deletion qiskit/transpiler/preset_passmanagers/level1.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
]
Expand Down Expand Up @@ -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),
Expand Down
26 changes: 25 additions & 1 deletion qiskit/transpiler/preset_passmanagers/level2.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
]
Expand Down Expand Up @@ -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),
Expand Down
22 changes: 21 additions & 1 deletion qiskit/transpiler/preset_passmanagers/level3.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
]
Expand Down Expand Up @@ -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),
Expand Down
18 changes: 18 additions & 0 deletions releasenotes/notes/squ-gate-name-785b7896300a92ef.yaml
Original file line number Diff line number Diff line change
@@ -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).