quarkcircuit 0.3.6.dev0__tar.gz → 0.3.7__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 (24) hide show
  1. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/PKG-INFO +1 -1
  2. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/pyproject.toml +1 -1
  3. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/__init__.py +1 -2
  4. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/backend.py +5 -3
  5. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/layout.py +11 -6
  6. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/routing.py +3 -3
  7. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/translate.py +1 -1
  8. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/transpiler.py +3 -3
  9. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quarkcircuit.egg-info/PKG-INFO +1 -1
  10. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quarkcircuit.egg-info/SOURCES.txt +0 -1
  11. quarkcircuit-0.3.6.dev0/quark/circuit/test_transpiler.py +0 -176
  12. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/README.md +0 -0
  13. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/basepasses.py +0 -0
  14. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/dag.py +0 -0
  15. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/decompose.py +0 -0
  16. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/matrix.py +0 -0
  17. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/optimize.py +0 -0
  18. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/quantumcircuit.py +0 -0
  19. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/quantumcircuit_helpers.py +0 -0
  20. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quark/circuit/utils.py +0 -0
  21. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quarkcircuit.egg-info/dependency_links.txt +0 -0
  22. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quarkcircuit.egg-info/requires.txt +0 -0
  23. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/quarkcircuit.egg-info/top_level.txt +0 -0
  24. {quarkcircuit-0.3.6.dev0 → quarkcircuit-0.3.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quarkcircuit
3
- Version: 0.3.6.dev0
3
+ Version: 0.3.7
4
4
  Summary: Construction, visualization, and transpilation of quantum circuits
5
5
  Author-email: Xiaoxiao Xiao <xiaoxx@baqis.ac.cn>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "quarkcircuit"
7
- version = "0.3.6dev"
7
+ version = "0.3.7"
8
8
  authors = [
9
9
  { name="Xiaoxiao Xiao", email="xiaoxx@baqis.ac.cn" }
10
10
  ]
@@ -48,5 +48,4 @@ from .decompose import ThreeQubitGateDecompose
48
48
  from .layout import Layout
49
49
  from .routing import SabreRouting
50
50
  from .translate import TranslateToBasisGates
51
- from .optimize import GateCompressor
52
- from .test_transpiler import call_quark_transpiler
51
+ from .optimize import GateCompressor
@@ -24,15 +24,14 @@ This module contains the Backend class, which processes superconducting chip inf
24
24
  import networkx as nx
25
25
  import numpy as np
26
26
  from typing import Literal
27
+ import requests
28
+ import json
27
29
 
28
30
  def load_chip_basic_info(chip_name):
29
- import requests
30
- import json
31
31
  session = requests.Session()
32
32
  URL = 'https://quafu-sqc.baqis.ac.cn'
33
33
  info0 = session.get(f'{URL}/task/backendtest/{chip_name}1')
34
34
  chip_info = json.loads(info0.content.decode())
35
-
36
35
  if chip_info:
37
36
  print(f'{chip_name} configuration loading done!')
38
37
  return chip_info
@@ -56,6 +55,7 @@ class Backend:
56
55
  self.priority_qubits = self.chip_info['priority_qubits']
57
56
  self.qubits_with_attributes = self._collect_qubits_with_attributes()
58
57
  self.couplers_with_attributes = self._collect_couplers_with_attributes()
58
+ self.two_qubit_gate_basis = self.chip_info['global_info']['two_qubit_gate_basis'].lower()
59
59
  elif chip in ['Baihua','Dongling','Haituo','Yunmeng','Miaofeng','Yudu','Hongluo']:
60
60
  self.chip_name = chip
61
61
  try:
@@ -67,6 +67,7 @@ class Backend:
67
67
  self.priority_qubits = self.chip_info['priority_qubits']
68
68
  self.qubits_with_attributes = self._collect_qubits_with_attributes()
69
69
  self.couplers_with_attributes = self._collect_couplers_with_attributes()
70
+ self.two_qubit_gate_basis = self.chip_info['global_info']['two_qubit_gate_basis'].lower()
70
71
 
71
72
  elif chip == 'Custom':
72
73
  self.chip_name = chip
@@ -75,6 +76,7 @@ class Backend:
75
76
  self.qubits_with_attributes = list()
76
77
  self.couplers_with_attributes = list()
77
78
  self.priority_qubits = []
79
+ self.two_qubit_gate_basis = 'cz'
78
80
  else:
79
81
  raise(ValueError(f'Wrong chip name! {chip}'))
80
82
 
@@ -339,7 +339,8 @@ class Layout:
339
339
  if len(target_qubits) != self.nqubits:
340
340
  raise(ValueError(f'The number of qubits {len(target_qubits)} in target_qubits does not match the number of qubits {self.nqubits} in the circuit.'))
341
341
  # check qubits existance and fidelity
342
- subgraph = self.graph.subgraph(target_qubits)
342
+ subgraph = self.graph.subgraph(target_qubits).copy()
343
+ subgraph.graph["normal_order"] = target_qubits
343
344
  for node in target_qubits:
344
345
  if subgraph.has_node(node):
345
346
  fidelity = nx.get_node_attributes(subgraph,'fidelity')[node]
@@ -369,7 +370,8 @@ class Layout:
369
370
  priority_qubits_list = self.priority_qubits
370
371
  for qubits in priority_qubits_list:
371
372
  if len(qubits) == self.nqubits:
372
- subgraph = self.graph.subgraph(qubits)
373
+ subgraph = self.graph.subgraph(qubits).copy()
374
+ subgraph.graph["normal_order"] = qubits
373
375
  if nx.is_connected(subgraph):
374
376
  coupling_map = list(subgraph.edges)
375
377
  print(f'Physical qubits layout {list(qubits)} are derived from the chip backend priority qubits, with the corresponding coupling being {coupling_map}.')
@@ -385,9 +387,10 @@ class Layout:
385
387
  qubit, fidelity = self.select_qubit_from_backend()
386
388
  #The selected qubit has the highest single-qubit gate fidelity.
387
389
  print(f'The selected physical qubit {qubit} is recommend, with single-qubit gate fidelity {fidelity}')
388
- subgraph = self.graph.subgraph([qubit])
390
+ subgraph = self.graph.subgraph([qubit]).copy()
391
+ subgraph.graph["normal_order"] = [qubit]
389
392
  return subgraph
390
- elif 1< self.nqubits <= self.algorithm_switch_threshold:
393
+ elif 1 < self.nqubits <= self.algorithm_switch_threshold:
391
394
  key_first = select_criteria['key']
392
395
  topology_first = select_criteria['topology']
393
396
  all_keys = ['fidelity_var','fidelity_mean']
@@ -404,7 +407,8 @@ class Layout:
404
407
  if physical_qubits_layout == []:
405
408
  raise(ValueError(f'Unable to find a suitable layout. If this message appears, please contact the developer for assistance.'))
406
409
  physical_qubits_layout = list(physical_qubits_layout)
407
- subgraph = self.graph.subgraph(physical_qubits_layout)
410
+ subgraph = self.graph.subgraph(physical_qubits_layout).copy()
411
+ subgraph.graph["normal_order"] = physical_qubits_layout
408
412
  coupling_map = list(subgraph.edges)
409
413
  print(f'Physical qubits layout {physical_qubits_layout} are selected by the Transpile algorithm using key = {key} and topology = {topology}, \nwith the corresponding coupling being {coupling_map}.')
410
414
  subgraph_fidelity = np.array([self.edge_fidelitys[(min(edge),max(edge))] for edge in subgraph.edges])
@@ -414,7 +418,8 @@ class Layout:
414
418
  return subgraph
415
419
  elif self.nqubits > self.algorithm_switch_threshold:
416
420
  physical_qubits_layout = self.get_BFS_layout()
417
- subgraph = self.graph.subgraph(physical_qubits_layout)
421
+ subgraph = self.graph.subgraph(physical_qubits_layout).copy()
422
+ subgraph.graph["normal_order"] = physical_qubits_layout
418
423
  coupling_map = list(subgraph.edges)
419
424
  print(f'Physical qubits layout {physical_qubits_layout} are selected by BFS algorithm with the corresponding coupling being {coupling_map}.')
420
425
  subgraph_fidelity = np.array([self.edge_fidelitys[(min(edge),max(edge))] for edge in subgraph.edges])
@@ -117,8 +117,8 @@ class SabreRouting(TranspilerPass):
117
117
  super().__init__()
118
118
  self.coupling_graph = subgraph
119
119
  self.distance_matrix = floyd_warshall_numpy(subgraph)
120
- self.physical_qubits = list(subgraph.nodes) # list(sorted(subgraph.nodes()))
121
- self.physical_qubits_index = dict(zip(self.physical_qubits,range(len(self.physical_qubits))))
120
+ self.physical_qubits = subgraph.graph['normal_order'] # list(sorted(subgraph.nodes()))
121
+ self.physical_qubits_index = dict(zip(list(subgraph.nodes),range(len(subgraph.nodes))))
122
122
  self.initial_mapping = initial_mapping
123
123
  self.do_random_choice = do_random_choice
124
124
  self.iterations = iterations
@@ -209,7 +209,7 @@ class SabreRouting(TranspilerPass):
209
209
  if len(set(virtual_qubits)) != len(set(self.physical_qubits)):
210
210
  raise(ValueError(f'The number of virtual qubits does not match the number of physical qubits.{virtual_qubits} {self.physical_qubits}'))
211
211
  if self.initial_mapping == 'trivial':
212
- v2p = dict(zip(virtual_qubits,sorted(self.physical_qubits)))
212
+ v2p = dict(zip(virtual_qubits,self.physical_qubits))
213
213
  elif self.initial_mapping == 'random':
214
214
  shuffle_physical_qubits = random.sample(self.physical_qubits,len(self.physical_qubits))
215
215
  v2p = dict(zip(virtual_qubits,shuffle_physical_qubits))
@@ -127,5 +127,5 @@ class TranslateToBasisGates(TranspilerPass):
127
127
  raise(TypeError(f'Input {gate} gate is not support to basic gates now.'))
128
128
 
129
129
  new_qc.gates = new
130
- print('Mapping to basic gates done !')
130
+ print(f'Mapping to basic gates done ! {self.two_qubit_gate_basis}')
131
131
  return new_qc
@@ -75,17 +75,17 @@ class Transpiler:
75
75
  if optimize_level == 0:
76
76
  passes = [ThreeQubitGateDecompose(),
77
77
  SabreRouting(subgraph,initial_mapping='trivial',do_random_choice=False,iterations=1),
78
- TranslateToBasisGates(convert_single_qubit_gate_to_u=True,two_qubit_gate_basis='cz'),
78
+ TranslateToBasisGates(convert_single_qubit_gate_to_u=True,two_qubit_gate_basis=self.chip_backend.two_qubit_gate_basis),
79
79
  ]
80
80
  elif optimize_level == 1:
81
81
  passes = [ThreeQubitGateDecompose(),
82
82
  SabreRouting(subgraph,initial_mapping='trivial',do_random_choice=False,iterations=5),
83
- TranslateToBasisGates(convert_single_qubit_gate_to_u=True,two_qubit_gate_basis='cz'),
83
+ TranslateToBasisGates(convert_single_qubit_gate_to_u=True,two_qubit_gate_basis=self.chip_backend.two_qubit_gate_basis),
84
84
  GateCompressor()]
85
85
  elif optimize_level == 2:
86
86
  passes = [ThreeQubitGateDecompose(),
87
87
  SabreRouting(subgraph,initial_mapping='random',do_random_choice=True,iterations=5),
88
- TranslateToBasisGates(convert_single_qubit_gate_to_u=True,two_qubit_gate_basis='cz'),
88
+ TranslateToBasisGates(convert_single_qubit_gate_to_u=True,two_qubit_gate_basis=self.chip_backend.two_qubit_gate_basis),
89
89
  GateCompressor()]
90
90
  else:
91
91
  raise(ValueError(f'Currently, only optimize_level values of 0 or 1 are supported.'))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quarkcircuit
3
- Version: 0.3.6.dev0
3
+ Version: 0.3.7
4
4
  Summary: Construction, visualization, and transpilation of quantum circuits
5
5
  Author-email: Xiaoxiao Xiao <xiaoxx@baqis.ac.cn>
6
6
  License-Expression: MIT
@@ -11,7 +11,6 @@ quark/circuit/optimize.py
11
11
  quark/circuit/quantumcircuit.py
12
12
  quark/circuit/quantumcircuit_helpers.py
13
13
  quark/circuit/routing.py
14
- quark/circuit/test_transpiler.py
15
14
  quark/circuit/translate.py
16
15
  quark/circuit/transpiler.py
17
16
  quark/circuit/utils.py
@@ -1,176 +0,0 @@
1
- import networkx as nx
2
- import json,copy
3
- from .quantumcircuit import QuantumCircuit
4
- from .quantumcircuit_helpers import one_qubit_gates_available,one_qubit_parameter_gates_available
5
- from .backend import Backend
6
- from .layout import Layout
7
- from .decompose import ThreeQubitGateDecompose
8
- from .routing import SabreRouting
9
- from .translate import TranslateToBasisGates
10
- from .optimize import GateCompressor
11
-
12
- from .dag import qc2dag
13
- from pathlib import Path
14
-
15
- def call_quark_transpiler(qc:QuantumCircuit|list|str,chip_name:str,compile:bool, options:dict,dev=False,return_qlisp=True):
16
- """ Transpiler for quantum cloud.
17
-
18
- Args:
19
- qc (QuantumCircuit | list | str): _description_
20
- chip_name (str): _description_
21
- compile (bool): _description_
22
- options (dict): _description_
23
- dev (bool, optional): _description_. Defaults to False.
24
- return_qlisp (bool, optional): _description_. Defaults to True.
25
-
26
- Returns:
27
- _type_: _description_
28
- """
29
- if dev:
30
- with open(Path.home()/f'Desktop/home/test/{chip_name}1.json') as f:
31
- chip_info = json.loads(f.read())
32
- chip_backend = Backend(chip_info)
33
- chip_backend.chip_name = chip_name
34
- else:
35
- chip_backend = Backend(chip_name)
36
-
37
- two_qubit_gate_basis = chip_backend.chip_info['global_info']['two_qubit_gate_basis'].lower()
38
-
39
- # 初始化线路,检查线路中的门是否都支持。
40
- if isinstance(qc, QuantumCircuit):
41
- quarkQC = qc
42
- elif isinstance(qc, str):
43
- quarkQC = QuantumCircuit().from_openqasm2(qc)
44
- elif isinstance(qc, list):
45
- quarkQC = QuantumCircuit().from_qlisp(qc)
46
- else:
47
- raise(TypeError(f'The qc format is incorrect, only str, list and QuantumCircuit are supported. The format you provided is {type(qc)}.'))
48
-
49
- # check measure 是否存在,且位于线路末尾
50
- dag = qc2dag(quarkQC)
51
- n_measure = 0
52
- insert_barrier = False
53
- for node in dag.nodes():
54
- if 'measure' in node:
55
- n_measure += 1
56
- if dag.out_degree(node) > 0:
57
- gate = node.split('_')[0]
58
- raise(ValueError(f'There are gate {gate} after the measurement gate.'))
59
- for predecessor in dag.predecessors(node):
60
- if 'barrier' not in predecessor:
61
- insert_barrier = True
62
- # 如果 measure 不存在,add barrier, add measure
63
- if n_measure == 0:
64
- print('There is no measurement gate in the circuit, quarkcircuit will add measure for all qubits.')
65
- quarkQC.barrier()
66
- quarkQC.ncbits = len(quarkQC.qubits)
67
- quarkQC.measure(quarkQC.qubits,[i for i in range(quarkQC.ncbits)])
68
- # 如果 measure存在 但没有隔离则添加隔离
69
- if n_measure > 0 and insert_barrier:
70
- new = []
71
- measure_gates = []
72
- barrier_gates = [('barrier',tuple(quarkQC.qubits))]
73
- for gate_info in quarkQC.gates:
74
- gate = gate_info[0]
75
- if gate == 'measure':
76
- measure_gates.append(gate_info)
77
- else:
78
- new.append(gate_info)
79
- quarkQC.gates = new + barrier_gates + measure_gates
80
-
81
- # delay duration
82
- for gate_info in quarkQC.gates:
83
- if gate_info[0] == 'delay':
84
- duration = gate_info[1] #quarkcircuit unit is ns
85
- if duration*1e-9 > 100e-6:
86
- raise(ValueError(f'The maximum delay is 100us, you provided is {duration} ns.'))
87
-
88
- # compile
89
- if compile:
90
- # 'options':{"target_qubits":[],"optimze_level":1}
91
- set_target_qubits = options.get('target_qubits',[])
92
- set_optimize_level = options.get('optimize_level',1)
93
- subgraph = Layout(len(quarkQC.qubits),chip_backend).select_layout(target_qubits=set_target_qubits,
94
- use_chip_priority=True,
95
- select_criteria={ 'key': 'fidelity_var','topology': 'linear' })
96
- quarkQC_compiled = ThreeQubitGateDecompose().run(quarkQC)
97
-
98
- if set_optimize_level == 0:
99
- quarkQC_compiled= SabreRouting(subgraph,initial_mapping='trivial',do_random_choice=False,iterations=1).run(quarkQC_compiled)
100
- elif set_optimize_level == 1:
101
- quarkQC_compiled = SabreRouting(subgraph,initial_mapping='trivial',do_random_choice=False,iterations=5).run(quarkQC_compiled)
102
- elif set_optimize_level == 2:
103
- quarkQC_compiled = SabreRouting(subgraph,initial_mapping='random',do_random_choice=True,iterations=5).run(quarkQC_compiled)
104
- else:
105
- raise(ValueError('More optimize_level is not support now!'))
106
-
107
- quarkQC_half_compiled = copy.deepcopy(quarkQC_compiled)
108
- quarkQC_half_compiled = TranslateToBasisGates(convert_single_qubit_gate_to_u=False,two_qubit_gate_basis=two_qubit_gate_basis).run(quarkQC_half_compiled)
109
- quarkQC_half_compiled = GateCompressor().run(quarkQC_half_compiled)
110
-
111
- if two_qubit_gate_basis == 'cx':
112
- two_qubit_gate_basis = 'cz'
113
- quarkQC_compiled = TranslateToBasisGates(convert_single_qubit_gate_to_u=True,two_qubit_gate_basis=two_qubit_gate_basis).run(quarkQC_compiled)
114
- quarkQC_compiled = GateCompressor().run(quarkQC_compiled)
115
- else:
116
- gates_availale = list(one_qubit_gates_available.keys()) \
117
- + list(one_qubit_parameter_gates_available.keys()) \
118
- + ['barrier','measure','delay'] + [two_qubit_gate_basis]#chip 支持的语法
119
- if 'cz' in gates_availale:
120
- gates_availale.append('cx')
121
-
122
- collect_two_qubit_gates = []
123
- for gate_info in quarkQC.gates:
124
- gate = gate_info[0]
125
- if gate not in gates_availale:
126
- raise(ValueError(f'The {gate} gate you provided is not supported by the current chip. Please convert to basis gates.'))
127
- if gate in ['cx','cz','iswap']:
128
- collect_two_qubit_gates.append(gate_info)
129
-
130
- # check qubits existance and fidelity
131
- subgraph = chip_backend.graph.subgraph(quarkQC.qubits)
132
- for node in quarkQC.qubits:
133
- if subgraph.has_node(node):
134
- fidelity = nx.get_node_attributes(subgraph,'fidelity')[node]
135
- if fidelity == 0.:
136
- raise(ValueError(f'The physical qubit {node} selected by the user is died.'))
137
- else:
138
- raise(KeyError(f'Physical qubit {node} does not exit.'))
139
- # check edge fidelity and connectivity
140
-
141
- is_connected = nx.is_connected(subgraph)
142
- for _, fidelity in nx.get_edge_attributes(subgraph,'fidelity').items():
143
- if fidelity == 0.:
144
- is_connected = False
145
- if is_connected is False:
146
- raise(ValueError(f'The physical qubit layout {quarkQC.qubits} selected by the user is not connected.'))
147
-
148
- for two_qubit_gates_info in collect_two_qubit_gates:
149
- gate,qubit1,qubit2 = two_qubit_gates_info
150
- if subgraph.has_edge(qubit1, qubit2):
151
- continue
152
- else:
153
- raise(ValueError(f'The {two_qubit_gates_info} cannot be executed directly by the chip. Please insert SWAP gates or reselect the layout.'))
154
- quarkQC_half_compiled = quarkQC
155
- quarkQC_compiled = quarkQC
156
-
157
- # check CZ
158
- ncz = quarkQC_compiled.ncz
159
- if ncz > 200:
160
- raise(ValueError(f'The number of two-qubit gates in the circuit is {ncz} exceeds 100.'))
161
-
162
- if return_qlisp:
163
- return quarkQC_compiled.to_qlisp,quarkQC_half_compiled.to_openqasm2
164
- else:
165
- return quarkQC_compiled,quarkQC_half_compiled
166
-
167
- if __name__ == '__main__':
168
- nqubits = 4
169
- qc = QuantumCircuit(nqubits)
170
- for i in range(1,nqubits):
171
- qc.cx(0,i)
172
- qc.barrier()
173
- qc.measure_all()
174
- qct_qlisp,qct_qasm = call_quark_transpiler(qc,'Baihua',True,{},)
175
- print(qct_qlisp)
176
- print(qct_qasm)