quarkcircuit 0.2.17__tar.gz → 0.3.0.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/PKG-INFO +4 -15
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/README.md +1 -1
- quarkcircuit-0.3.0.dev2/pyproject.toml +22 -0
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/__init__.py +6 -3
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/backend.py +67 -18
- quarkcircuit-0.3.0.dev2/quark/circuit/basepasses.py +41 -0
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/dag.py +5 -1
- quarkcircuit-0.2.17/quark/circuit/decompose_helpers.py → quarkcircuit-0.3.0.dev2/quark/circuit/decompose.py +137 -14
- quarkcircuit-0.2.17/quark/circuit/layout_helpers.py → quarkcircuit-0.3.0.dev2/quark/circuit/layout.py +74 -69
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/matrix.py +68 -3
- quarkcircuit-0.2.17/quark/circuit/optimize_helpers.py → quarkcircuit-0.3.0.dev2/quark/circuit/optimize.py +219 -84
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/quantumcircuit.py +237 -41
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/quantumcircuit_helpers.py +95 -35
- quarkcircuit-0.2.17/quark/circuit/routing_helpers.py → quarkcircuit-0.3.0.dev2/quark/circuit/routing.py +181 -169
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/test_transpiler.py +35 -19
- quarkcircuit-0.3.0.dev2/quark/circuit/translate.py +124 -0
- quarkcircuit-0.3.0.dev2/quark/circuit/transpiler.py +79 -0
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quarkcircuit.egg-info/PKG-INFO +4 -15
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quarkcircuit.egg-info/SOURCES.txt +6 -5
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quarkcircuit.egg-info/requires.txt +0 -1
- quarkcircuit-0.2.17/MANIFEST.in +0 -1
- quarkcircuit-0.2.17/pyproject.toml +0 -36
- quarkcircuit-0.2.17/quark/circuit/transpiler.py +0 -395
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/utils.py +0 -0
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quarkcircuit.egg-info/dependency_links.txt +0 -0
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quarkcircuit.egg-info/top_level.txt +0 -0
- {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/setup.cfg +0 -0
|
@@ -1,25 +1,14 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: quarkcircuit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0.dev2
|
|
4
4
|
Summary: Construction, visualization, and transpilation of quantum circuits
|
|
5
5
|
Author-email: Xiaoxiao Xiao <xiaoxx@baqis.ac.cn>
|
|
6
|
-
|
|
7
|
-
Classifier: Intended Audience :: Developers
|
|
8
|
-
Classifier: Intended Audience :: Science/Research
|
|
9
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
-
Classifier: Natural Language :: Chinese (Simplified)
|
|
11
|
-
Classifier: Natural Language :: English
|
|
12
|
-
Classifier: Operating System :: Microsoft :: Windows
|
|
13
|
-
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
-
Classifier: Operating System :: MacOS :: MacOS X
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
-
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
6
|
+
License-Expression: MIT
|
|
17
7
|
Requires-Python: >=3.10
|
|
18
8
|
Description-Content-Type: text/markdown
|
|
19
9
|
Requires-Dist: numpy
|
|
20
10
|
Requires-Dist: scipy
|
|
21
11
|
Requires-Dist: networkx
|
|
22
|
-
Requires-Dist: quarkstudio
|
|
23
12
|
|
|
24
13
|
# QuarkCircuit
|
|
25
14
|
|
|
@@ -49,7 +38,7 @@ pip install quarkcircuit
|
|
|
49
38
|
|
|
50
39
|
## First experience
|
|
51
40
|
|
|
52
|
-
See [quarkcircuit example](https://quarkstudio.readthedocs.io/en/latest/usage/
|
|
41
|
+
See [quarkcircuit example](https://quarkstudio.readthedocs.io/en/latest/usage/code/transpiler/)
|
|
53
42
|
|
|
54
43
|
## License
|
|
55
44
|
|
|
@@ -26,7 +26,7 @@ pip install quarkcircuit
|
|
|
26
26
|
|
|
27
27
|
## First experience
|
|
28
28
|
|
|
29
|
-
See [quarkcircuit example](https://quarkstudio.readthedocs.io/en/latest/usage/
|
|
29
|
+
See [quarkcircuit example](https://quarkstudio.readthedocs.io/en/latest/usage/code/transpiler/)
|
|
30
30
|
|
|
31
31
|
## License
|
|
32
32
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "quarkcircuit"
|
|
7
|
+
version = "0.3.0dev2"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name="Xiaoxiao Xiao", email="xiaoxx@baqis.ac.cn" }
|
|
10
|
+
]
|
|
11
|
+
description = "Construction, visualization, and transpilation of quantum circuits"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
license = "MIT"
|
|
14
|
+
requires-python = ">=3.10"
|
|
15
|
+
dependencies = [
|
|
16
|
+
"numpy",
|
|
17
|
+
"scipy",
|
|
18
|
+
"networkx",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[tool.setuptools]
|
|
22
|
+
packages = ["quark.circuit"]
|
|
@@ -44,6 +44,9 @@ from .matrix import *
|
|
|
44
44
|
from .transpiler import Transpiler
|
|
45
45
|
from .dag import dag2qc,qc2dag,draw_dag
|
|
46
46
|
from .backend import Backend
|
|
47
|
-
from .
|
|
48
|
-
from .
|
|
49
|
-
from .
|
|
47
|
+
from .decompose import ThreeQubitGateDecompose
|
|
48
|
+
from .layout import Layout
|
|
49
|
+
from .routing import SabreRouting
|
|
50
|
+
from .translate import TranslateToBasisGates
|
|
51
|
+
from .optimize import GateCompressor
|
|
52
|
+
from .test_transpiler import call_quark_transpiler
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
r"""
|
|
21
21
|
This module contains the Backend class, which processes superconducting chip information into an undirected graph representation. It also supports the creation of custom undirected graphs to serve as virtual chips.
|
|
22
22
|
"""
|
|
23
|
+
|
|
23
24
|
import networkx as nx
|
|
24
25
|
import numpy as np
|
|
25
26
|
from typing import Literal
|
|
@@ -55,9 +56,12 @@ class Backend:
|
|
|
55
56
|
self.priority_qubits = self.chip_info['priority_qubits']
|
|
56
57
|
self.qubits_with_attributes = self._collect_qubits_with_attributes()
|
|
57
58
|
self.couplers_with_attributes = self._collect_couplers_with_attributes()
|
|
58
|
-
elif chip in ['Baihua','
|
|
59
|
+
elif chip in ['Baihua','Dongling','Haituo','Yunmeng','Miaofeng',]:
|
|
59
60
|
self.chip_name = chip
|
|
60
|
-
|
|
61
|
+
try:
|
|
62
|
+
self.chip_info = load_chip_basic_info(chip)
|
|
63
|
+
except:
|
|
64
|
+
raise(ValueError(f'{chip} is under maintenance, configuration information is unavailable'))
|
|
61
65
|
print('The last calibration time was',self.chip_info['calibration_time'])
|
|
62
66
|
self.size = self.chip_info['size']
|
|
63
67
|
self.priority_qubits = self.chip_info['priority_qubits']
|
|
@@ -85,7 +89,27 @@ class Backend:
|
|
|
85
89
|
"""
|
|
86
90
|
return self.get_graph()
|
|
87
91
|
|
|
92
|
+
def edge_filtered_graph(self,thres = 0.6):
|
|
93
|
+
"""Create a subgraph by filtering out edges with fidelity below a specified threshold.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
thres (float, optional): The fidelity threshold. Defaults to 0.6.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
networkx.Graph: A new NetworkX graph object containing only edges with fidelity greater than or equal to the threshold.
|
|
100
|
+
"""
|
|
101
|
+
def edge_filter(u,v):
|
|
102
|
+
return self.graph[u][v].get("fidelity") >= thres
|
|
103
|
+
subgraph_view = nx.subgraph_view(self.graph,filter_edge=edge_filter)
|
|
104
|
+
return nx.Graph(subgraph_view)
|
|
105
|
+
|
|
88
106
|
def _collect_qubits_with_attributes(self):
|
|
107
|
+
"""Collect qubit indices and their associated attributes from chip information.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
list: A list of tuples, where each tuple contains a qubit index (int) and its attributes (dict)
|
|
111
|
+
extracted from self.chip_info['qubits_info']
|
|
112
|
+
"""
|
|
89
113
|
qubits_with_attributes = []
|
|
90
114
|
for key in self.chip_info['qubits_info'].keys():
|
|
91
115
|
qubit = int(key.split('Q')[1])
|
|
@@ -93,6 +117,12 @@ class Backend:
|
|
|
93
117
|
return qubits_with_attributes
|
|
94
118
|
|
|
95
119
|
def _collect_couplers_with_attributes(self):
|
|
120
|
+
"""Collect coupler information including qubit indices and their associated attributes from chip information.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
list: A list of tuples, where each tuple contains two qubit indices (int, int) and the coupler attributes (dict)
|
|
124
|
+
extracted from self.chip_info['couplers_info'].
|
|
125
|
+
"""
|
|
96
126
|
couplers_with_attributes = []
|
|
97
127
|
for key in self.chip_info['couplers_info'].keys():
|
|
98
128
|
qubit1, qubit2 = self.chip_info['couplers_info'][key]['qubits_index']
|
|
@@ -110,8 +140,9 @@ class Backend:
|
|
|
110
140
|
G.add_edges_from(self.couplers_with_attributes)
|
|
111
141
|
return G
|
|
112
142
|
|
|
113
|
-
def draw(self,show_couplers_fidelity:bool = False, show_quibts_attributes:Literal['T1','T2','fidelity','frequency','']='',
|
|
114
|
-
|
|
143
|
+
def draw(self,show_couplers_fidelity:bool = False, show_quibts_attributes:Literal['T1','T2','fidelity','frequency','']='',
|
|
144
|
+
show_qubits_index:bool=False,show_couplers_index:bool=False,
|
|
145
|
+
highlight_nodes:list = [], save_svg_fname: str|None = None,):
|
|
115
146
|
"""Draw the chip layout.
|
|
116
147
|
|
|
117
148
|
Args:
|
|
@@ -124,6 +155,8 @@ class Backend:
|
|
|
124
155
|
- 'frequancy': Display the frequency of qubits (in GHz).
|
|
125
156
|
- '': Display no attributes.
|
|
126
157
|
Defaults to ''.
|
|
158
|
+
show_qubits_index (bool, optional): Whether to display index for each qubit. Defaults to False.
|
|
159
|
+
show_couplers_index (bool, optional): Whether to display index for each coupler. Defaults to False.
|
|
127
160
|
highlight_nodes (list, optional): A list of qubits to highlight. Defaults to an empty list [].
|
|
128
161
|
save_svg_fname (str | None, optional):
|
|
129
162
|
The filename for saving the drawing as an SVG. If None, the drawing will not be saved.
|
|
@@ -141,8 +174,23 @@ class Backend:
|
|
|
141
174
|
from matplotlib.colors import Normalize,LinearSegmentedColormap
|
|
142
175
|
from matplotlib.cm import ScalarMappable
|
|
143
176
|
|
|
177
|
+
|
|
144
178
|
edge_fidelity = nx.get_edge_attributes(self.graph, 'fidelity')
|
|
179
|
+
node_attributes = nx.get_node_attributes(self.graph,show_quibts_attributes)
|
|
145
180
|
if show_couplers_fidelity:
|
|
181
|
+
if set(list(edge_fidelity.values())) == {None}:
|
|
182
|
+
print('The two-qubit gate fidelity is N/A now.')
|
|
183
|
+
is_edge_info_avaliable = False
|
|
184
|
+
else:
|
|
185
|
+
is_edge_info_avaliable = True
|
|
186
|
+
if show_quibts_attributes:
|
|
187
|
+
if set(list(node_attributes.values())) == {None}:
|
|
188
|
+
print('The qubit attributes is N/A now.')
|
|
189
|
+
is_node_info_avaliable = False
|
|
190
|
+
else:
|
|
191
|
+
is_node_info_avaliable = True
|
|
192
|
+
|
|
193
|
+
if show_couplers_fidelity is True and is_edge_info_avaliable is True:
|
|
146
194
|
min_fidelity = sorted(list(edge_fidelity.values()))[0]
|
|
147
195
|
max_fidelity = sorted(list(edge_fidelity.values()))[-1]
|
|
148
196
|
edge_norm = Normalize(vmin = min_fidelity, vmax = max_fidelity)
|
|
@@ -153,35 +201,36 @@ class Backend:
|
|
|
153
201
|
|
|
154
202
|
edge_labels = {}
|
|
155
203
|
for k,v in edge_fidelity.items():
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
204
|
+
if v == None:
|
|
205
|
+
fidelity = ''
|
|
206
|
+
else:
|
|
207
|
+
fidelity = np.round(v, 3)
|
|
208
|
+
if show_couplers_fidelity is True and is_edge_info_avaliable is True:
|
|
209
|
+
if show_couplers_index:
|
|
159
210
|
edge_labels[k] = self.graph.edges[k].get('index')
|
|
160
211
|
else:
|
|
161
212
|
edge_labels[k] = fidelity
|
|
162
213
|
else:
|
|
163
214
|
edge_labels[k] = self.graph.edges[k].get('index')
|
|
164
215
|
|
|
165
|
-
if show_quibts_attributes != '':
|
|
166
|
-
node_attributes = nx.get_node_attributes(self.graph,show_quibts_attributes)
|
|
216
|
+
if show_quibts_attributes != '' and is_node_info_avaliable is True:
|
|
167
217
|
min_attributes = sorted(list(node_attributes.values()))[0]
|
|
168
218
|
max_attributes = sorted(list(node_attributes.values()))[-1]
|
|
169
219
|
node_norm = Normalize(vmin = min_attributes, vmax = max_attributes)
|
|
170
220
|
node_cmap = LinearSegmentedColormap.from_list('truncated_blues', plt.get_cmap('Blues')(np.linspace(0.31, 1.0, 1000))) #plt.get_cmap('Blues')
|
|
171
|
-
|
|
172
221
|
node_colors = [ScalarMappable(norm = node_norm, cmap = node_cmap).to_rgba(attribute) for attribute in node_attributes.values()]
|
|
173
222
|
if show_quibts_attributes == 'fidelity':
|
|
174
|
-
if
|
|
223
|
+
if show_qubits_index:
|
|
175
224
|
node_labels = {node:node for node in self.graph.nodes()}
|
|
176
225
|
else:
|
|
177
226
|
node_labels = {node: np.round(attr, 3) for node, attr in node_attributes.items()} # 保留三位有效数字
|
|
178
227
|
else:
|
|
179
|
-
if
|
|
228
|
+
if show_qubits_index:
|
|
180
229
|
node_labels = {node:node for node in self.graph.nodes()}
|
|
181
230
|
else:
|
|
182
231
|
node_labels = {node: np.round(attr, 2) for node, attr in node_attributes.items()} # 保留两位有效数字
|
|
183
232
|
node_font_size = 8
|
|
184
|
-
if show_couplers_fidelity:
|
|
233
|
+
if show_couplers_fidelity is True and is_edge_info_avaliable is True:
|
|
185
234
|
figsize = (15, 15)
|
|
186
235
|
else:
|
|
187
236
|
figsize = (15, 13.5)
|
|
@@ -189,7 +238,7 @@ class Backend:
|
|
|
189
238
|
node_colors = ['#083776' for node in self.graph.nodes()]
|
|
190
239
|
node_labels = {node:node for node in self.graph.nodes()}
|
|
191
240
|
node_font_size = 10
|
|
192
|
-
if show_couplers_fidelity:
|
|
241
|
+
if show_couplers_fidelity is True and is_edge_info_avaliable is True:
|
|
193
242
|
figsize = (15, 13.5)
|
|
194
243
|
else:
|
|
195
244
|
figsize = (15, 13)
|
|
@@ -226,7 +275,7 @@ class Backend:
|
|
|
226
275
|
nx.draw_networkx_labels(self.graph,pos,labels=node_labels,font_size=node_font_size, font_color='white')
|
|
227
276
|
nx.draw_networkx_edge_labels(self.graph, pos, edge_labels=edge_labels,font_size=8, font_color='white',bbox=dict(facecolor='none', edgecolor='none'))
|
|
228
277
|
|
|
229
|
-
if show_quibts_attributes:
|
|
278
|
+
if show_quibts_attributes != '' and is_node_info_avaliable is True:
|
|
230
279
|
if show_quibts_attributes == 'T1':
|
|
231
280
|
show_label = 'T1 ($\mu s$)'
|
|
232
281
|
elif show_quibts_attributes == 'T2':
|
|
@@ -237,13 +286,13 @@ class Backend:
|
|
|
237
286
|
show_label = 'Frequency (GHz)'
|
|
238
287
|
node_sm = ScalarMappable(cmap=node_cmap, norm=node_norm)
|
|
239
288
|
node_sm.set_array(list(node_attributes.values())) # 设置包含数据的数组
|
|
240
|
-
if show_couplers_fidelity:
|
|
289
|
+
if show_couplers_fidelity and is_edge_info_avaliable is True:
|
|
241
290
|
node_cbar = fig.colorbar(node_sm, ax=ax, orientation='horizontal',pad=0.07, fraction=0.03, aspect=25)
|
|
242
291
|
else:
|
|
243
292
|
node_cbar = fig.colorbar(node_sm, ax=ax, orientation='horizontal',pad=0.001, fraction=0.0333, aspect=25)
|
|
244
293
|
node_cbar.set_label(show_label)
|
|
245
294
|
|
|
246
|
-
if show_couplers_fidelity:
|
|
295
|
+
if show_couplers_fidelity is True and is_edge_info_avaliable is True:
|
|
247
296
|
edge_sm = ScalarMappable(cmap=edge_cmap, norm=edge_norm)# 创建颜色条
|
|
248
297
|
edge_sm.set_array(list(edge_fidelity.values())) # 设置包含数据的数组
|
|
249
298
|
edge_cbar = fig.colorbar(edge_sm, ax=ax, orientation='horizontal', pad=0.001, fraction=0.0333, aspect=25)# 调整颜色条大小和位置,放置在底部
|
|
@@ -252,7 +301,7 @@ class Backend:
|
|
|
252
301
|
xlim = ax.get_xlim()
|
|
253
302
|
ylim = ax.get_ylim()
|
|
254
303
|
xpos = (xlim[0] + xlim[1]) / 2
|
|
255
|
-
ypos = ylim[1] * 0.
|
|
304
|
+
ypos = ylim[1] * 0.96
|
|
256
305
|
ax.text(xpos, ypos, f'{self.chip_name}', va='center', ha='center', fontsize=24, fontweight='bold', color='k', family='serif')
|
|
257
306
|
|
|
258
307
|
if save_svg_fname:
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright (c) 2024 XX Xiao
|
|
2
|
+
|
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
# of this software and associated documentation files(the "Software"), to deal
|
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
# furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
|
11
|
+
# all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
19
|
+
|
|
20
|
+
r"""
|
|
21
|
+
This module contains the TranspilerPass class, an abstract base class for defining transpiler passes that transform or optimize quantum circuits. Subclasses must implement the run method to process QuantumCircuit objects.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from abc import ABC, abstractmethod
|
|
25
|
+
from .quantumcircuit import QuantumCircuit
|
|
26
|
+
|
|
27
|
+
# 抽象基类
|
|
28
|
+
class TranspilerPass(ABC):
|
|
29
|
+
"""Abstract base class for defining transpiler passes that transform or optimize quantum circuits.
|
|
30
|
+
"""
|
|
31
|
+
def __init__(self):
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def run(self, qc:QuantumCircuit):
|
|
36
|
+
"""Execute the transpiler pass on a quantum circuit.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
qc (QuantumCircuit): The quantum circuit to be processed by this transpiler pass.
|
|
40
|
+
"""
|
|
41
|
+
pass
|
|
@@ -27,6 +27,7 @@ from .quantumcircuit import QuantumCircuit
|
|
|
27
27
|
from .quantumcircuit_helpers import (
|
|
28
28
|
one_qubit_gates_available,
|
|
29
29
|
two_qubit_gates_available,
|
|
30
|
+
three_qubit_gates_available,
|
|
30
31
|
one_qubit_parameter_gates_available,
|
|
31
32
|
two_qubit_parameter_gates_available,
|
|
32
33
|
functional_gates_available,
|
|
@@ -107,6 +108,8 @@ def dag2qc(dag: 'nx.DiGraph',nqubits: int, ncbits: int|None = None) -> 'QuantumC
|
|
|
107
108
|
new.append((gate,qubits[0]))
|
|
108
109
|
elif gate in two_qubit_gates_available.keys():
|
|
109
110
|
new.append((gate,qubits[0],qubits[1]))
|
|
111
|
+
elif gate in three_qubit_gates_available.keys():
|
|
112
|
+
new.append((gate,qubits[0],qubits[1],qubits[2]))
|
|
110
113
|
elif gate in one_qubit_parameter_gates_available.keys():
|
|
111
114
|
params = dag.nodes[node]['params']
|
|
112
115
|
new.append((gate,*params,qubits[0]))
|
|
@@ -120,7 +123,8 @@ def dag2qc(dag: 'nx.DiGraph',nqubits: int, ncbits: int|None = None) -> 'QuantumC
|
|
|
120
123
|
elif gate == 'barrier':
|
|
121
124
|
new.append((gate,tuple(qubits)))
|
|
122
125
|
elif gate == 'delay':
|
|
123
|
-
|
|
126
|
+
duration = dag.nodes[node]['duration']
|
|
127
|
+
new.append((gate,duration,tuple(qubits)))
|
|
124
128
|
elif gate == 'reset':
|
|
125
129
|
new.append((gate,qubits[0]))
|
|
126
130
|
|
|
@@ -17,12 +17,32 @@
|
|
|
17
17
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
18
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
19
19
|
|
|
20
|
-
r"""Some common decomposition methods for
|
|
20
|
+
r"""Some common decomposition methods for two-qubit and three-qubit gates."""
|
|
21
21
|
|
|
22
|
+
import numpy as np
|
|
22
23
|
from typing import Literal
|
|
23
24
|
from .utils import u3_decompose
|
|
24
25
|
from .matrix import u_mat
|
|
25
|
-
|
|
26
|
+
from .quantumcircuit import QuantumCircuit
|
|
27
|
+
from .basepasses import TranspilerPass
|
|
28
|
+
|
|
29
|
+
def u_dot_u(u_info1: tuple, u_info2: tuple) -> tuple:
|
|
30
|
+
"""Carry out u @ u and return a new u information
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
u_info1 (tuple): u gate information like ('u', 1.5707963267948966, 0.0, 3.141592653589793, 0)
|
|
34
|
+
u_info2 (tuple): u gate information like ('u', 1.5707963267948966, 0.0, 3.141592653589793, 0)
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
tuple: A new u gate information
|
|
38
|
+
"""
|
|
39
|
+
assert(u_info1[-1] == u_info2[-1])
|
|
40
|
+
u_mat1 = u_mat(*u_info1[1:-1])
|
|
41
|
+
u_mat2 = u_mat(*u_info2[1:-1])
|
|
42
|
+
|
|
43
|
+
new_u = u_mat2 @ u_mat1
|
|
44
|
+
theta, phi, lamda, _ = u3_decompose(new_u)
|
|
45
|
+
return ('u', theta, phi, lamda, u_info1[-1])
|
|
26
46
|
|
|
27
47
|
def h2u(qubit: int) -> tuple:
|
|
28
48
|
"""Convert H gate to U3 gate tuple.
|
|
@@ -346,20 +366,123 @@ def rzz_decompose(theta:float, qubit1:int, qubit2:int, convert_single_qubit_gate
|
|
|
346
366
|
gates += cx_decompose(qubit1,qubit2,convert_single_qubit_gate_to_u,two_qubit_gate_basis)
|
|
347
367
|
return gates
|
|
348
368
|
|
|
349
|
-
def
|
|
350
|
-
"""
|
|
369
|
+
def ccx_decompose(control_qubit1: int, control_qubit2: int, target_qubit: int,):
|
|
370
|
+
"""Decompose ccx gate. Reference: A biological sequence comparison algorithm using quantum computers
|
|
351
371
|
|
|
352
372
|
Args:
|
|
353
|
-
|
|
354
|
-
|
|
373
|
+
control_qubit1 (int): The qubit used as the first control.
|
|
374
|
+
control_qubit2 (int): The qubit used as the second control.
|
|
375
|
+
target_qubit (int): The qubit targeted by the gate.
|
|
355
376
|
|
|
356
377
|
Returns:
|
|
357
|
-
|
|
378
|
+
list: A list of single- and two-qubit gates.
|
|
358
379
|
"""
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
380
|
+
gates = [
|
|
381
|
+
('h',target_qubit),
|
|
382
|
+
('cx',control_qubit2,target_qubit),
|
|
383
|
+
('tdg',target_qubit),
|
|
384
|
+
('cx',control_qubit1,target_qubit),
|
|
385
|
+
('t',target_qubit),
|
|
386
|
+
('cx',control_qubit2,target_qubit),
|
|
387
|
+
('t',control_qubit2),
|
|
388
|
+
('tdg',target_qubit),
|
|
389
|
+
('cx',control_qubit1,target_qubit),
|
|
390
|
+
('cx',control_qubit1,control_qubit2),
|
|
391
|
+
('t',target_qubit),
|
|
392
|
+
('t',control_qubit1),
|
|
393
|
+
('tdg',control_qubit2),
|
|
394
|
+
('h',target_qubit),
|
|
395
|
+
('cx',control_qubit1,control_qubit2),
|
|
396
|
+
]
|
|
397
|
+
return gates
|
|
398
|
+
|
|
399
|
+
def cswap_decompose(control_qubit1: int, control_qubit2: int, target_qubit: int,):
|
|
400
|
+
"""Decompose cswap gate. Reference: http://threeplusone.com/gates
|
|
401
|
+
|
|
402
|
+
Args:
|
|
403
|
+
control_qubit1 (int): The qubit used as the first control.
|
|
404
|
+
control_qubit2 (int): The qubit used as the second control.
|
|
405
|
+
target_qubit (int): The qubit targeted by the gate.
|
|
406
|
+
|
|
407
|
+
Returns:
|
|
408
|
+
list: A list of single- and two-qubit gates.
|
|
409
|
+
"""
|
|
410
|
+
gates = [
|
|
411
|
+
('cx',target_qubit,control_qubit2),
|
|
412
|
+
('h',target_qubit),
|
|
413
|
+
('cx',control_qubit2,target_qubit),
|
|
414
|
+
('tdg',target_qubit),
|
|
415
|
+
('cx',control_qubit1,target_qubit),
|
|
416
|
+
('t',target_qubit),
|
|
417
|
+
('cx',control_qubit2,target_qubit),
|
|
418
|
+
('t',control_qubit2),
|
|
419
|
+
('tdg',target_qubit),
|
|
420
|
+
('cx',control_qubit1,target_qubit),
|
|
421
|
+
('cx',control_qubit1,control_qubit2),
|
|
422
|
+
('t',target_qubit),
|
|
423
|
+
('t',control_qubit1),
|
|
424
|
+
('tdg',control_qubit2),
|
|
425
|
+
('h',target_qubit),
|
|
426
|
+
('cx',control_qubit1,control_qubit2),
|
|
427
|
+
('cx',target_qubit,control_qubit2),
|
|
428
|
+
]
|
|
429
|
+
return gates
|
|
430
|
+
|
|
431
|
+
def ccz_decompose(control_qubit1: int, control_qubit2: int, target_qubit: int,):
|
|
432
|
+
"""Decompose ccz gate. Reference: http://threeplusone.com/gates
|
|
433
|
+
|
|
434
|
+
Args:
|
|
435
|
+
control_qubit1 (int): The qubit used as the first control.
|
|
436
|
+
control_qubit2 (int): The qubit used as the second control.
|
|
437
|
+
target_qubit (int): The qubit targeted by the gate.
|
|
438
|
+
|
|
439
|
+
Returns:
|
|
440
|
+
list: A list of single- and two-qubit gates.
|
|
441
|
+
"""
|
|
442
|
+
gates = [
|
|
443
|
+
('cx',control_qubit2,target_qubit),
|
|
444
|
+
('tdg',target_qubit),
|
|
445
|
+
('cx',control_qubit1,target_qubit),
|
|
446
|
+
('t',target_qubit),
|
|
447
|
+
('cx',control_qubit2,target_qubit),
|
|
448
|
+
('t',control_qubit2),
|
|
449
|
+
('tdg',target_qubit),
|
|
450
|
+
('cx',control_qubit1,target_qubit),
|
|
451
|
+
('cx',control_qubit1,control_qubit2),
|
|
452
|
+
('t',target_qubit),
|
|
453
|
+
('t',control_qubit1),
|
|
454
|
+
('tdg',control_qubit2),
|
|
455
|
+
('h',target_qubit),
|
|
456
|
+
('cx',control_qubit1,control_qubit2),
|
|
457
|
+
('h',target_qubit)
|
|
458
|
+
]
|
|
459
|
+
return gates
|
|
460
|
+
|
|
461
|
+
class ThreeQubitGateDecompose(TranspilerPass):
|
|
462
|
+
"""A transpiler pass that decomposes three-qubit gates into combinations of single- and two-qubit gates.
|
|
463
|
+
"""
|
|
464
|
+
def __init__(self):
|
|
465
|
+
super().__init__()
|
|
466
|
+
|
|
467
|
+
def run(self,qc:QuantumCircuit):
|
|
468
|
+
"""Decompose three-qubit gates in the quantum circuit into sequences of single- and two-qubit gates.
|
|
469
|
+
|
|
470
|
+
Args:
|
|
471
|
+
qc (QuantumCircuit): The quantum circuit to process.
|
|
472
|
+
|
|
473
|
+
Returns:
|
|
474
|
+
QuantumCircuit: A new quantum circuit with all three-qubit gates decomposed into single- and two-qubit gates.
|
|
475
|
+
"""
|
|
476
|
+
new = []
|
|
477
|
+
for gate_info in qc.gates:
|
|
478
|
+
if gate_info[0] == 'ccx':
|
|
479
|
+
new += ccx_decompose(*gate_info[1:])
|
|
480
|
+
elif gate_info[0] == 'ccz':
|
|
481
|
+
new += ccz_decompose(*gate_info[1:])
|
|
482
|
+
elif gate_info[0] == 'cswap':
|
|
483
|
+
new += cswap_decompose(*gate_info[1:])
|
|
484
|
+
else:
|
|
485
|
+
new.append(gate_info)
|
|
486
|
+
new_qc = qc.deepcopy()
|
|
487
|
+
new_qc.gates = new
|
|
488
|
+
return new_qc
|