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.
Files changed (27) hide show
  1. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/PKG-INFO +4 -15
  2. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/README.md +1 -1
  3. quarkcircuit-0.3.0.dev2/pyproject.toml +22 -0
  4. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/__init__.py +6 -3
  5. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/backend.py +67 -18
  6. quarkcircuit-0.3.0.dev2/quark/circuit/basepasses.py +41 -0
  7. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/dag.py +5 -1
  8. quarkcircuit-0.2.17/quark/circuit/decompose_helpers.py → quarkcircuit-0.3.0.dev2/quark/circuit/decompose.py +137 -14
  9. quarkcircuit-0.2.17/quark/circuit/layout_helpers.py → quarkcircuit-0.3.0.dev2/quark/circuit/layout.py +74 -69
  10. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/matrix.py +68 -3
  11. quarkcircuit-0.2.17/quark/circuit/optimize_helpers.py → quarkcircuit-0.3.0.dev2/quark/circuit/optimize.py +219 -84
  12. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/quantumcircuit.py +237 -41
  13. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/quantumcircuit_helpers.py +95 -35
  14. quarkcircuit-0.2.17/quark/circuit/routing_helpers.py → quarkcircuit-0.3.0.dev2/quark/circuit/routing.py +181 -169
  15. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/test_transpiler.py +35 -19
  16. quarkcircuit-0.3.0.dev2/quark/circuit/translate.py +124 -0
  17. quarkcircuit-0.3.0.dev2/quark/circuit/transpiler.py +79 -0
  18. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quarkcircuit.egg-info/PKG-INFO +4 -15
  19. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quarkcircuit.egg-info/SOURCES.txt +6 -5
  20. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quarkcircuit.egg-info/requires.txt +0 -1
  21. quarkcircuit-0.2.17/MANIFEST.in +0 -1
  22. quarkcircuit-0.2.17/pyproject.toml +0 -36
  23. quarkcircuit-0.2.17/quark/circuit/transpiler.py +0 -395
  24. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quark/circuit/utils.py +0 -0
  25. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quarkcircuit.egg-info/dependency_links.txt +0 -0
  26. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/quarkcircuit.egg-info/top_level.txt +0 -0
  27. {quarkcircuit-0.2.17 → quarkcircuit-0.3.0.dev2}/setup.cfg +0 -0
@@ -1,25 +1,14 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: quarkcircuit
3
- Version: 0.2.17
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
- Classifier: Development Status :: 5 - Production/Stable
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/quark/example/)
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/quark/example/)
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 .layout_helpers import Layout
48
- from .test_transpiler import call_quark_transpiler
49
- from .optimize_helpers import GateCompressor
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','Haituo1','Dongling1','Dongling2','Yunmeng1']:
59
+ elif chip in ['Baihua','Dongling','Haituo','Yunmeng','Miaofeng',]:
59
60
  self.chip_name = chip
60
- self.chip_info = load_chip_basic_info(chip)
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','']='', highlight_nodes:list = [],
114
- save_svg_fname: str|None = None,show_qubits_label:bool=False,show_couplers_label:bool=False):
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
- fidelity = np.round(v, 3)
157
- if show_couplers_fidelity:
158
- if show_couplers_label:
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 show_qubits_label:
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 show_qubits_label:
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.75
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
- new.append((gate,tuple(qubits)))
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 single-qubit and two-qubit gates."""
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
- import numpy as np
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 u_dot_u(u_info1: tuple, u_info2: tuple) -> tuple:
350
- """Carry out u @ u and return a new u information
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
- u_info1 (tuple): u gate information like ('u', 1.5707963267948966, 0.0, 3.141592653589793, 0)
354
- u_info2 (tuple): u gate information like ('u', 1.5707963267948966, 0.0, 3.141592653589793, 0)
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
- tuple: A new u gate information
378
+ list: A list of single- and two-qubit gates.
358
379
  """
359
- assert(u_info1[-1] == u_info2[-1])
360
- u_mat1 = u_mat(*u_info1[1:-1])
361
- u_mat2 = u_mat(*u_info2[1:-1])
362
-
363
- new_u = u_mat2 @ u_mat1
364
- theta, phi, lamda, _ = u3_decompose(new_u)
365
- return ('u', theta, phi, lamda, u_info1[-1])
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