-
Notifications
You must be signed in to change notification settings - Fork 3k
Add unitary synthesis plugin interface #6124
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
Changes from 1 commit
ad04aaa
1fb017b
1da2d87
0532a1e
19bb0c8
fece875
d9eda3b
b7678cf
5622895
566ebcf
0bb935e
faa260a
7808223
dd9211f
20c10b7
bd5c2ae
8f44c92
bb10dcc
04b72bc
291457a
9557aaf
b7a9873
bf8a6e5
4c52bfc
35709d5
449b6ac
78f84b4
1dd25b4
935ac01
44a186c
c161b9d
373f43d
def0a66
46db9ec
9c64267
9a0b941
f83c841
2e1726c
6b9d550
db38b8d
5e35056
3d9b783
c5f6f7f
e65c01a
ac9f85d
6f1eb05
303eb29
cc9fe27
d57351e
43c46f5
0e06b7d
d9f6884
0e5c637
5d8539a
aa2af0f
ba6a4a0
66bb763
7240065
9ca591a
9c12540
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
|
|
||
| import abc | ||
|
|
||
| import stevedore | ||
|
|
||
| class UnitarySynthesisPlugin(abc.ABC): | ||
| """Abstract plugin Synthesis plugin class | ||
|
|
||
| This class abstract class is | ||
|
|
||
| """ | ||
|
|
||
| @property | ||
| @abc.abstractmethod | ||
| def supports_basis_gates(self): | ||
| """Return whether the plugin supports taking basis_gates""" | ||
| pass | ||
|
|
||
| @property | ||
| @abc.abstractmethod | ||
| def supports_coupling_map(self): | ||
| """Return whether the plugin supports taking coupling_map""" | ||
| pass | ||
|
|
||
| @property | ||
| @abc.abstractmethod | ||
| def supports_approximation_degree(self): | ||
|
mtreinish marked this conversation as resolved.
Outdated
|
||
| """Return whether the plugin supports taking approximation_degree""" | ||
| pass | ||
|
|
||
| @abc.abstractmethod | ||
| def run(self, unitary, **options): | ||
| """Run synthesis for the given unitary | ||
|
|
||
| Args: | ||
| unitary (numpy.ndarray): The unitary | ||
|
|
||
| Returns: | ||
| DAGCircuit: The dag circuit representation of the unitary | ||
| """ | ||
| pass | ||
|
|
||
|
|
||
| class UnitarySynthesisPluginManager: | ||
|
|
||
| def __init__(self): | ||
| self.ext_plugins = stevedore.ExtensionManager( | ||
| 'qiskit.unitary_synthesis', invoke_on_load=True, | ||
| propagate_map_exceptions=True) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,11 +18,13 @@ | |
| from qiskit.converters import circuit_to_dag | ||
| from qiskit.transpiler.basepasses import TransformationPass | ||
| from qiskit.dagcircuit.dagcircuit import DAGCircuit | ||
| from qiskit.exceptions import QiskitError | ||
| from qiskit.extensions.quantum_initializer import isometry | ||
| from qiskit.quantum_info.synthesis import one_qubit_decompose | ||
| from qiskit.quantum_info.synthesis.two_qubit_decompose import TwoQubitBasisDecomposer | ||
| from qiskit.circuit.library.standard_gates import (iSwapGate, CXGate, CZGate, | ||
| RXXGate, ECRGate) | ||
| from qiskit.transpiler.passes.synthesis import plugin | ||
|
|
||
|
|
||
| def _choose_kak_gate(basis_gates): | ||
|
|
@@ -60,7 +62,9 @@ class UnitarySynthesis(TransformationPass): | |
|
|
||
| def __init__(self, | ||
| basis_gates: List[str], | ||
| approximation_degree: float = 1): | ||
| approximation_degree: float = 1, | ||
| coupling_map = None, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be better to pass a
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue with using a The one thing I thought about doing was making the api free form and just have the abstract |
||
| method: str = None): | ||
| """ | ||
| Synthesize unitaries over some basis gates. | ||
|
|
||
|
|
@@ -75,6 +79,9 @@ def __init__(self, | |
| super().__init__() | ||
| self._basis_gates = basis_gates | ||
| self._approximation_degree = approximation_degree | ||
| self.method = method | ||
| self._coupling_map = coupling_map | ||
| self.plugins = plugin.UnitarySynthesisPluginManager() | ||
|
|
||
| def run(self, dag: DAGCircuit) -> DAGCircuit: | ||
| """Run the UnitarySynthesis pass on `dag`. | ||
|
|
@@ -85,31 +92,62 @@ def run(self, dag: DAGCircuit) -> DAGCircuit: | |
| Returns: | ||
| Output dag with UnitaryGates synthesized to target basis. | ||
| """ | ||
| euler_basis = _choose_euler_basis(self._basis_gates) | ||
| kak_gate = _choose_kak_gate(self._basis_gates) | ||
| for node in dag.named_nodes('unitary'): | ||
| synth_dag = None | ||
| if not self.method: | ||
| method = 'default' | ||
| else: | ||
| method = self.method | ||
| if method not in self.plugins.ext_plugins: | ||
| raise QiskitError( | ||
| 'Specified method: %s not found in plugin list' % method) | ||
| plugin = self.plugins.ext_plugins[method].obj | ||
| kwargs = {} | ||
| if plugin.supports_basis_gates: | ||
| kwargs['basis_gates'] = self._basis_gates | ||
| if plugin.supports_coupling_map: | ||
| kwargs['coupling_map'] = self._coupling_map | ||
| if plugin.supports_approximation_degree: | ||
| kwargs['approximation_degree'] = self._approximation_degree | ||
| unitary = node.op.to_matrix() | ||
| synth_dag = plugin.run(unitary, **kwargs) | ||
| if synth_dag: | ||
| dag.substitute_node_with_dag(node, synth_dag) | ||
| return dag | ||
|
|
||
|
|
||
| class DefaultUnitarySynthesis(plugin.UnitarySynthesisPlugin): | ||
|
|
||
| def supports_basis_gates(self): | ||
| return True | ||
|
|
||
| def supports_coupling_map(self): | ||
| return False | ||
|
|
||
| def supports_approximation_degree(self): | ||
| return True | ||
|
|
||
| def run(self, unitary, **options): | ||
| basis_gates = options['basis_gates'] | ||
| approximation_degree = options['approximation_degree'] | ||
| euler_basis = _choose_euler_basis(basis_gates) | ||
| kak_gate = _choose_kak_gate(basis_gates) | ||
|
|
||
| decomposer1q, decomposer2q = None, None | ||
| if euler_basis is not None: | ||
| decomposer1q = one_qubit_decompose.OneQubitEulerDecomposer(euler_basis) | ||
| if kak_gate is not None: | ||
| decomposer2q = TwoQubitBasisDecomposer(kak_gate, euler_basis=euler_basis) | ||
|
|
||
| for node in dag.named_nodes('unitary'): | ||
|
|
||
| synth_dag = None | ||
| if len(node.qargs) == 1: | ||
| if decomposer1q is None: | ||
| continue | ||
| synth_dag = circuit_to_dag(decomposer1q._decompose(node.op.to_matrix())) | ||
| elif len(node.qargs) == 2: | ||
| if decomposer2q is None: | ||
| continue | ||
| synth_dag = circuit_to_dag(decomposer2q(node.op.to_matrix(), | ||
| basis_fidelity=self._approximation_degree)) | ||
| else: | ||
| synth_dag = circuit_to_dag( | ||
| isometry.Isometry(node.op.to_matrix(), 0, 0).definition) | ||
|
|
||
| dag.substitute_node_with_dag(node, synth_dag) | ||
|
|
||
| return dag | ||
| if unitary.shape == (2, 2): | ||
| if decomposer1q is None: | ||
| return None | ||
| synth_dag = circuit_to_dag(decomposer1q._decompose(unitary)) | ||
| elif unitary.shape == (4, 4): | ||
| if decomposer2q is None: | ||
| return None | ||
| synth_dag = circuit_to_dag(decomposer2q(unitary, | ||
| basis_fidelity=approximation_degree)) | ||
| else: | ||
| synth_dag = circuit_to_dag( | ||
| isometry.Isometry(unitary.op.to_matrix(), 0, 0).definition) | ||
| return synth_dag | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,3 +10,4 @@ dill>=0.3 | |
| fastjsonschema>=2.10 | ||
| python-constraint>=1.4 | ||
| python-dateutil>=2.8.0 | ||
| stevedore>=3.0.0 | ||
Uh oh!
There was an error while loading. Please reload this page.