quarkcircuit 0.3.0.dev2__tar.gz → 0.3.1__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.0.dev2 → quarkcircuit-0.3.1}/PKG-INFO +1 -1
  2. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/pyproject.toml +1 -1
  3. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/decompose.py +34 -0
  4. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/layout.py +58 -34
  5. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/matrix.py +12 -1
  6. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/quantumcircuit.py +44 -1
  7. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/quantumcircuit_helpers.py +75 -36
  8. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/test_transpiler.py +2 -2
  9. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/translate.py +3 -0
  10. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quarkcircuit.egg-info/PKG-INFO +1 -1
  11. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/README.md +0 -0
  12. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/__init__.py +0 -0
  13. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/backend.py +0 -0
  14. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/basepasses.py +0 -0
  15. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/dag.py +0 -0
  16. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/optimize.py +0 -0
  17. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/routing.py +0 -0
  18. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/transpiler.py +0 -0
  19. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quark/circuit/utils.py +0 -0
  20. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quarkcircuit.egg-info/SOURCES.txt +0 -0
  21. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quarkcircuit.egg-info/dependency_links.txt +0 -0
  22. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quarkcircuit.egg-info/requires.txt +0 -0
  23. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/quarkcircuit.egg-info/top_level.txt +0 -0
  24. {quarkcircuit-0.3.0.dev2 → quarkcircuit-0.3.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quarkcircuit
3
- Version: 0.3.0.dev2
3
+ Version: 0.3.1
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.0dev2"
7
+ version = "0.3.1"
8
8
  authors = [
9
9
  { name="Xiaoxiao Xiao", email="xiaoxx@baqis.ac.cn" }
10
10
  ]
@@ -366,6 +366,40 @@ def rzz_decompose(theta:float, qubit1:int, qubit2:int, convert_single_qubit_gate
366
366
  gates += cx_decompose(qubit1,qubit2,convert_single_qubit_gate_to_u,two_qubit_gate_basis)
367
367
  return gates
368
368
 
369
+
370
+ def cp_decompose(theta:float, control_qubit:int, target_qubit:int, convert_single_qubit_gate_to_u:bool) -> list:
371
+ """Decompose CPhase gate to U3 gates and CZ gates.
372
+
373
+ Args:
374
+ theta (float): The rotation angle of the gate.
375
+ control_qubit (int): The qubit used as control.
376
+ target_qubit (int): The qubit targeted by the gate.
377
+
378
+ Returns:
379
+ list: A list of U3 gates and CZ gates.
380
+ """
381
+ gates = []
382
+ if convert_single_qubit_gate_to_u:
383
+ gates.append(h2u(target_qubit))
384
+ else:
385
+ gates.append(('h',target_qubit))
386
+ gates.append(('cz', control_qubit, target_qubit))
387
+ if convert_single_qubit_gate_to_u:
388
+ gates.append(rx2u(theta/2,target_qubit))
389
+ else:
390
+ gates.append(('rx',theta/2,target_qubit))
391
+ gates.append(('cz', control_qubit, target_qubit))
392
+ if convert_single_qubit_gate_to_u:
393
+ gates.append(rz2u(-1*theta/2, control_qubit))
394
+ gates.append(h2u(target_qubit))
395
+ gates.append(rz2u(-1*theta/2,target_qubit))
396
+ else:
397
+ gates.append(('rz',-1*theta/2,control_qubit))
398
+ gates.append(('h',target_qubit))
399
+ gates.append(('rz',-1*theta/2,target_qubit))
400
+ return gates
401
+
402
+
369
403
  def ccx_decompose(control_qubit1: int, control_qubit2: int, target_qubit: int,):
370
404
  """Decompose ccx gate. Reference: A biological sequence comparison algorithm using quantum computers
371
405
 
@@ -312,6 +312,18 @@ class Layout:
312
312
  )
313
313
 
314
314
  return linear1_subgraph_list_sort[:num],linear2_subgraph_list_sort[:num],cycle_subgraph_list_sort[:num],nonlinear_subgraph_list_sort[:num]
315
+
316
+ def select_qubit_from_backend(self,):
317
+ # 当线路中只有一个qubit时,挑选单比特门保真度最大的比特
318
+
319
+ for nodes in nx.connected_components(self.graph):
320
+ if len(nodes) > 1:
321
+ subgraph = self.graph.subgraph(nodes)
322
+ break
323
+ node_fidelity_dic = nx.get_node_attributes(subgraph,'fidelity')
324
+ sorted_dict = dict(sorted(node_fidelity_dic.items(), key=lambda item: item[1], reverse=True))
325
+ qubit = list(sorted_dict.keys())[0]
326
+ return qubit, sorted_dict[qubit]
315
327
 
316
328
  def select_layout_from_backend(self,
317
329
  key: Literal['fidelity_mean', 'fidelity_var'] = 'fidelity_var',
@@ -391,47 +403,59 @@ class Layout:
391
403
  if is_connected is False:
392
404
  raise(ValueError(f'The physical qubit layout {target_qubits} constructed from target_qubits is not connected.'))
393
405
  coupling_map = list(subgraph.edges)
394
- print(f'Physical qubits layout {target_qubits} are user-defined, with the corresponding coupling being {coupling_map}.')
395
- subgraph_fidelity = np.array([data['fidelity'] for _, _, data in subgraph.edges(data=True)])
396
- fidelity_mean = np.mean(subgraph_fidelity)
397
- fidelity_var = np.var(subgraph_fidelity)
398
- print(f'The average fidelity of the coupler(s) between the selected qubits is {fidelity_mean}, and the variance of the fidelity is {fidelity_var}.')
406
+ print(f'Physical qubits layout {target_qubits} are user-defined, with the corresponding coupling being {coupling_map}.')
407
+
408
+ if len(subgraph.edges())>0:
409
+ subgraph_fidelity = np.array([data['fidelity'] for _, _, data in subgraph.edges(data=True)])
410
+ fidelity_mean = np.mean(subgraph_fidelity)
411
+ fidelity_var = np.var(subgraph_fidelity)
412
+ print(f'The average fidelity of the coupler(s) between the selected qubits is {fidelity_mean}, and the variance of the fidelity is {fidelity_var}.')
399
413
  return subgraph
400
- if use_chip_priority: # 如果列表中没有满足的比特则启动筛选,todos:把筛选机制转成数据库
414
+ if use_chip_priority: # 如果列表中没有满足的比特则启动筛选,如果是单比特则保留原比特,不再筛选,todos:把筛选机制转成数据库
401
415
  priority_qubits_list = self.priority_qubits
402
416
  for qubits in priority_qubits_list:
403
417
  if len(qubits) == self.nqubits:
404
418
  subgraph = self.graph.subgraph(qubits)
405
419
  coupling_map = list(subgraph.edges)
406
420
  print(f'Physical qubits layout {list(qubits)} are derived from the chip backend priority qubits, with the corresponding coupling being {coupling_map}.')
407
- subgraph_fidelity = np.array([data['fidelity'] for _, _, data in subgraph.edges(data=True)])
408
- fidelity_mean = np.mean(subgraph_fidelity)
409
- fidelity_var = np.var(subgraph_fidelity)
410
- print(f'The average fidelity of the coupler(s) between the selected qubits is {fidelity_mean}, and the variance of the fidelity is {fidelity_var}.')
421
+ if len(subgraph.edges())>0:
422
+ subgraph_fidelity = np.array([data['fidelity'] for _, _, data in subgraph.edges(data=True)])
423
+ fidelity_mean = np.mean(subgraph_fidelity)
424
+ fidelity_var = np.var(subgraph_fidelity)
425
+ print(f'The average fidelity of the coupler(s) between the selected qubits is {fidelity_mean}, and the variance of the fidelity is {fidelity_var}.')
411
426
  return subgraph
412
427
  print(f'No priority qubits with {self.nqubits} qubits found. it will check the select_criteria for search')
413
428
 
414
- key_first = select_criteria['key']
415
- topology_first = select_criteria['topology']
416
- all_keys = ['fidelity_var','fidelity_mean']
417
- all_topologys = ['linear1','linear2','cycle','nonlinear']
418
- all_keys.remove(key_first)
419
- all_topologys.remove(topology_first)
420
- sorted_keys = [key_first,] + all_keys
421
- sorted_topologys = [topology_first,] + all_topologys
422
- physical_qubits_layout = []
423
- for key, topology in product(sorted_keys,sorted_topologys):
424
- physical_qubits_layout = self.select_layout_from_backend(key=key,topology=topology)
425
- if physical_qubits_layout != []:
426
- break
427
- if physical_qubits_layout == []:
428
- raise(ValueError(f'Unable to find a suitable layout. If this message appears, please contact the developer for assistance.'))
429
- physical_qubits_layout = list(physical_qubits_layout)
430
- subgraph = self.graph.subgraph(physical_qubits_layout)
431
- coupling_map = list(subgraph.edges)
432
- 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}.')
433
- subgraph_fidelity = np.array([data['fidelity'] for _, _, data in subgraph.edges(data=True)])
434
- fidelity_mean = np.mean(subgraph_fidelity)
435
- fidelity_var = np.var(subgraph_fidelity)
436
- print(f'The average fidelity of the coupler(s) between the selected qubits is {fidelity_mean}, and the variance of the fidelity is {fidelity_var}.')
437
- return subgraph
429
+ if self.nqubits == 1:
430
+ qubit, fidelity = self.select_qubit_from_backend()
431
+ #The selected qubit has the highest single-qubit gate fidelity.
432
+ print(f'The selected physical qubit {qubit} is recommend, with single-qubit gate fidelity {fidelity}')
433
+ subgraph = self.graph.subgraph([qubit])
434
+ return subgraph
435
+ elif self.nqubits > 1:
436
+ key_first = select_criteria['key']
437
+ topology_first = select_criteria['topology']
438
+ all_keys = ['fidelity_var','fidelity_mean']
439
+ all_topologys = ['linear1','linear2','cycle','nonlinear']
440
+ all_keys.remove(key_first)
441
+ all_topologys.remove(topology_first)
442
+ sorted_keys = [key_first,] + all_keys
443
+ sorted_topologys = [topology_first,] + all_topologys
444
+ physical_qubits_layout = []
445
+ for key, topology in product(sorted_keys,sorted_topologys):
446
+ physical_qubits_layout = self.select_layout_from_backend(key=key,topology=topology)
447
+ if physical_qubits_layout != []:
448
+ break
449
+ if physical_qubits_layout == []:
450
+ raise(ValueError(f'Unable to find a suitable layout. If this message appears, please contact the developer for assistance.'))
451
+ physical_qubits_layout = list(physical_qubits_layout)
452
+ subgraph = self.graph.subgraph(physical_qubits_layout)
453
+ coupling_map = list(subgraph.edges)
454
+ 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}.')
455
+ subgraph_fidelity = np.array([data['fidelity'] for _, _, data in subgraph.edges(data=True)])
456
+ fidelity_mean = np.mean(subgraph_fidelity)
457
+ fidelity_var = np.var(subgraph_fidelity)
458
+ print(f'The average fidelity of the coupler(s) between the selected qubits is {fidelity_mean}, and the variance of the fidelity is {fidelity_var}.')
459
+ return subgraph
460
+ else:
461
+ raise(ValueError('Wrong qubits error!'))
@@ -316,6 +316,16 @@ def rzz_mat(theta: float) -> np.ndarray:
316
316
  ], dtype=complex
317
317
  )
318
318
 
319
+ def cp_mat(theta: float) -> np.ndarray:
320
+ return np.array(
321
+ [
322
+ [1, 0, 0, 0],
323
+ [0, 1, 0, 0],
324
+ [0, 0, 1, 0],
325
+ [0, 0, 0, np.exp(1j*theta)]
326
+ ], dtype=complex
327
+ )
328
+
319
329
  gate_matrix_dict = {
320
330
  'id':id_mat, 'x':x_mat, 'y':y_mat, 'z':z_mat, 'h':h_mat,
321
331
  's':s_mat, 'sdg':sdg_mat, 't':t_mat, 'tdg':tdg_mat, 'sx':sx_mat, 'sxdg':sxdg_mat,
@@ -323,5 +333,6 @@ gate_matrix_dict = {
323
333
  'cx':cx_mat, 'cnot':cx_mat, 'cy':cy_mat, 'cz':cz_mat,
324
334
  'rx':rx_mat, 'ry':ry_mat, 'rz':rz_mat,
325
335
  'p':p_mat, 'u':u_mat,'r':r_mat,
326
- 'rxx':rxx_mat,'ryy':ryy_mat,'rzz':rzz_mat,'ccz':ccz_mat,'ccx':ccx_mat,'cswap':cswap_mat,
336
+ 'rxx':rxx_mat,'ryy':ryy_mat,'rzz':rzz_mat, 'cp':cp_mat,
337
+ 'ccz':ccz_mat,'ccx':ccx_mat,'cswap':cswap_mat,
327
338
  }
@@ -802,7 +802,40 @@ class QuantumCircuit:
802
802
  raise ValueError(f"Qubit index conflict: qubit1 and qubit2 are both {qubit1}")
803
803
  else:
804
804
  raise ValueError("Qubit index out of range")
805
-
805
+
806
+ def cp(self, theta: float, control_qubit: int, target_qubit:int) -> None:
807
+ r"""
808
+ Add a Cphase gate.
809
+
810
+ $$
811
+ Rzz(\theta) = I \otimes |0\rangle\lange 0| + P \otimes |1\rangle\langle 1| =
812
+ \begin{bmatrix}
813
+ 1 & 0 & 0 & 0 \\
814
+ 0 & 1 & 0 & 0 \\
815
+ 0 & 0 & 1 & 0 \\
816
+ 0 & 0 & 0 & e^{i\theta}
817
+ \end{bmatrix}.
818
+ $$
819
+
820
+ Args:
821
+ theta (float): The rotation angle of the gate.
822
+ control_qubit (int): The qubit to apply the gate to.
823
+ target_qubit (int): The qubit to apply the gate to.
824
+
825
+ Raises:
826
+ ValueError: If qubit out of circuit range.
827
+ """
828
+ if max(control_qubit, target_qubit) < self.nqubits:
829
+ if control_qubit != target_qubit:
830
+ self.gates.append(('cp', theta, control_qubit, target_qubit))
831
+ self._add_qubits(control_qubit, target_qubit)
832
+ if isinstance(theta,str):
833
+ self.params_value[theta] = theta
834
+ else:
835
+ raise ValueError(f"Qubit index conflict: qubit1 and qubit2 are both {control_qubit}")
836
+ else:
837
+ raise ValueError("Qubit index out of range")
838
+
806
839
  def shallow_apply_value(self,params_dic):
807
840
  for k,v in self.params_value.items():
808
841
  self.params_value[k] = k
@@ -1183,6 +1216,15 @@ class QuantumCircuit:
1183
1216
  qlisp.append(('iSWAP', tuple('Q'+str(i) for i in gate_info[1:])))
1184
1217
  elif gate in three_qubit_gates_available.keys():
1185
1218
  qlisp.append((gate.upper(), tuple('Q'+str(i) for i in gate_info[1:])))
1219
+ elif gate in ['cp']:
1220
+ if isinstance(gate_info[1],float):
1221
+ qlisp.append(((gate.upper(), gate_info[1]),tuple('Q'+str(i) for i in gate_info[1:])))
1222
+ elif isinstance(gate_info[1],str):
1223
+ param = self.params_value[gate_info[1]]
1224
+ if isinstance(param,float):
1225
+ qlisp.append(((gate.upper(), param),tuple('Q'+str(i) for i in gate_info[2:])))
1226
+ else:
1227
+ raise(ValueError(f'please apply value for parameter {param}'))
1186
1228
  elif gate in ['rx', 'ry', 'rz', 'p']:
1187
1229
  if isinstance(gate_info[1],float):
1188
1230
  qlisp.append(((gate.capitalize(), gate_info[1]), 'Q'+str(gate_info[2])))
@@ -1328,6 +1370,7 @@ class QuantumCircuit:
1328
1370
  'rxx':qc.rxx,
1329
1371
  'ryy':qc.ryy,
1330
1372
  'rzz':qc.rzz,
1373
+ 'cp':qc.cp,
1331
1374
  }
1332
1375
  functional_gates_in_qiskit = {
1333
1376
  'barrier':qc.barrier,
@@ -30,10 +30,10 @@ one_qubit_gates_available = {
30
30
  }
31
31
  two_qubit_gates_available = {
32
32
  'cx':'●X', 'cnot':'●X', 'cy':'●Y', 'cz':'●Z', 'swap':'XX', 'iswap':'✶✶',
33
- }
34
- three_qubit_gates_available = {'ccz':'●●●','ccx':'●●X','cswap':'●XX'}
33
+ }
34
+ three_qubit_gates_available = {'ccz':'●●●','ccx':'●●X','cswap':'●XX'}
35
35
  one_qubit_parameter_gates_available = {'rx':'Rx', 'ry':'Ry', 'rz':'Rz', 'p':'P', 'u':'U', 'u3':'U', 'r':'R'}
36
- two_qubit_parameter_gates_available = {'rxx':'Rxx', 'ryy':'Ryy', 'rzz':'Rzz',}
36
+ two_qubit_parameter_gates_available = {'rxx':'Rxx', 'ryy':'Ryy', 'rzz':'Rzz','cp':'●P'} # CPhase
37
37
  functional_gates_available = {'barrier':'░', 'measure':'M', 'reset':'|0>','delay':'Delay'}
38
38
 
39
39
  def convert_gate_info_to_dag_info(nqubits:int,qubits:list,gates:list,show_qubits:bool=True) -> tuple[list,list]:
@@ -271,6 +271,9 @@ def parse_openqasm2_to_gates(openqasm2_str) -> None:
271
271
  continue
272
272
  else:
273
273
  raise(ValueError(f"Sorry, an unrecognized OpenQASM 2.0 syntax {gate} was detected by quarkcircuit. Please contact the developer for assistance."))
274
+
275
+ if cbit_used == []:
276
+ cbit_used = [i for i in range(len(set(qubit_used)))]
274
277
  return new,set(qubit_used),set(cbit_used)
275
278
 
276
279
  def parse_qlisp_to_gates(qlisp: list) -> tuple[list, list, list]:
@@ -338,6 +341,12 @@ def parse_qlisp_to_gates(qlisp: list) -> tuple[list, list, list]:
338
341
  #elif gate[0] in ['rfUnitary']:
339
342
  # qubit0 = int(gate_info[1].split('Q')[1])
340
343
  # new.append(('r', gate[1], gate[2], qubit0))
344
+ elif gate[0] in ['CU']:
345
+ qubit1 = int(gate_info[1][0].split('Q')[1])
346
+ qubit2 = int(gate_info[1][1].split('Q')[1])
347
+ new.append((gate[0].lower(),gate[1],qubit1,qubit2))
348
+ qubit_used.append(qubit1)
349
+ qubit_used.append(qubit2)
341
350
  elif gate in ['Cnot']:
342
351
  qubit1 = int(gate_info[1][0].split('Q')[1])
343
352
  qubit2 = int(gate_info[1][1].split('Q')[1])
@@ -483,41 +492,71 @@ def generate_gates_layerd(nqubits:int,ncbits:int,gates:list,params_value:dict) -
483
492
  gates_layerd[idx+1][i] = '│'
484
493
  break
485
494
  elif gate in two_qubit_parameter_gates_available.keys():
486
- #print(gate_info)
487
- pos0 = min(gate_info[2],gate_info[3])
488
- pos1 = max(gate_info[2],gate_info[3])
489
- if isinstance(gate_info[1],float):
490
- theta0_str = is_multiple_of_pi(gate_info[1])
491
- elif isinstance(gate_info[1],str):
492
- param = params_value[gate_info[1]]
493
- if isinstance(param,float):
494
- theta0_str = is_multiple_of_pi(param)
495
- elif isinstance(param,str):
496
- theta0_str = param
497
- gate_express = two_qubit_parameter_gates_available[gate]+f'({theta0_str})'
498
- if len(gate_express)%2 == 0:
499
- gate_express += ' '
500
- for idx in range(len(gates_layerd)-1,-1,-1):
501
- if gates_layerd[idx][2*pos0:2*pos1+1] != list('─ ')*(pos1-pos0)+['─']:
502
- dif0 = (len(gate_express) - 1)//2
503
- if pos0 == gate_info[2]:
504
- gates_layerd[idx+1][2*pos0] = '┌' + '─'*dif0 +'0'+'─'*dif0 + '┐'
505
- gates_layerd[idx+1][2*pos1] = '└' + '─'*dif0 +'1'+'─'*dif0 + '┘'
506
- lines_use.append(2*pos0)
507
- lines_use.append(2*pos0 + 1)
508
- lines_use.append(2*pos1)
509
- lines_use.append(2*pos1 + 1)
510
- elif pos0 == gate_info[3]:
511
- gates_layerd[idx+1][2*pos0] = '┌' + '─'*dif0 +'1'+'─'*dif0 + '┐'
512
- gates_layerd[idx+1][2*pos1] = '└' + '─'*dif0 +'0'+'─'*dif0 + '┘'
495
+ if gate in ['cp']:
496
+ pos0 = min(gate_info[2],gate_info[3])
497
+ pos1 = max(gate_info[2],gate_info[3])
498
+ if isinstance(gate_info[1],float):
499
+ theta0_str = is_multiple_of_pi(gate_info[1])
500
+ elif isinstance(gate_info[1],str):
501
+ param = params_value[gate_info[1]]
502
+ if isinstance(param,float):
503
+ theta0_str = is_multiple_of_pi(param)
504
+ elif isinstance(param,str):
505
+ theta0_str = param
506
+ gate_express = two_qubit_parameter_gates_available[gate][1]+f'({theta0_str})'
507
+ if len(gate_express) % 2 == 0:
508
+ gate_express = two_qubit_parameter_gates_available[gate][1]+f'({theta0_str})─'
509
+ for idx in range(len(gates_layerd)-1,-1,-1):
510
+ if gates_layerd[idx][2*pos0:2*pos1+1] != list('─ ')*(pos1-pos0)+['─']:
511
+ gates_layerd[idx+1][2*gate_info[2]] = (len(gate_express)//2)*'─' + two_qubit_parameter_gates_available[gate][0] + (len(gate_express)//2)*'─'
512
+ gates_layerd[idx+1][2*gate_info[3]] = gate_express
513
513
  lines_use.append(2*pos0)
514
- lines_use.append(2*pos0 + 1)
514
+ lines_use.append(2*pos0+1)
515
515
  lines_use.append(2*pos1)
516
- lines_use.append(2*pos1 + 1)
517
- for i in range(2*pos0+1,2*pos1):
518
- gates_layerd[idx+1][i] = '│' + ' '*len(gate_express) + '│'
519
- gates_layerd[idx+1][2*pos0 + (pos1-pos0)] = '│' + gate_express + ''
520
- break
516
+ lines_use.append(2*pos1+1)
517
+ for i in range(2*pos0+1,2*pos1):
518
+ if i % 2 == 0:
519
+ gates_layerd[idx+1][i] = (len(gate_express)//2)*'─' + '│' + (len(gate_express)//2)*''
520
+ else:
521
+ gates_layerd[idx+1][i] = (len(gate_express)//2)*' ' + '│' + (len(gate_express)//2)*' '
522
+
523
+ break
524
+
525
+ else:
526
+ pos0 = min(gate_info[2],gate_info[3])
527
+ pos1 = max(gate_info[2],gate_info[3])
528
+ if isinstance(gate_info[1],float):
529
+ theta0_str = is_multiple_of_pi(gate_info[1])
530
+ elif isinstance(gate_info[1],str):
531
+ param = params_value[gate_info[1]]
532
+ if isinstance(param,float):
533
+ theta0_str = is_multiple_of_pi(param)
534
+ elif isinstance(param,str):
535
+ theta0_str = param
536
+ gate_express = two_qubit_parameter_gates_available[gate]+f'({theta0_str})'
537
+ if len(gate_express)%2 == 0:
538
+ gate_express += ' '
539
+ for idx in range(len(gates_layerd)-1,-1,-1):
540
+ if gates_layerd[idx][2*pos0:2*pos1+1] != list('─ ')*(pos1-pos0)+['─']:
541
+ dif0 = (len(gate_express) - 1)//2
542
+ if pos0 == gate_info[2]:
543
+ gates_layerd[idx+1][2*pos0] = '┌' + '─'*dif0 +'0'+'─'*dif0 + '┐'
544
+ gates_layerd[idx+1][2*pos1] = '└' + '─'*dif0 +'1'+'─'*dif0 + '┘'
545
+ lines_use.append(2*pos0)
546
+ lines_use.append(2*pos0 + 1)
547
+ lines_use.append(2*pos1)
548
+ lines_use.append(2*pos1 + 1)
549
+ elif pos0 == gate_info[3]:
550
+ gates_layerd[idx+1][2*pos0] = '┌' + '─'*dif0 +'1'+'─'*dif0 + '┐'
551
+ gates_layerd[idx+1][2*pos1] = '└' + '─'*dif0 +'0'+'─'*dif0 + '┘'
552
+ lines_use.append(2*pos0)
553
+ lines_use.append(2*pos0 + 1)
554
+ lines_use.append(2*pos1)
555
+ lines_use.append(2*pos1 + 1)
556
+ for i in range(2*pos0+1,2*pos1):
557
+ gates_layerd[idx+1][i] = '│' + ' '*len(gate_express) + '│'
558
+ gates_layerd[idx+1][2*pos0 + (pos1-pos0)] = '│' + gate_express + '│'
559
+ break
521
560
  elif gate in one_qubit_parameter_gates_available.keys():
522
561
  if gate == 'u':
523
562
  if isinstance(gate_info[1],float):
@@ -96,7 +96,7 @@ def call_quark_transpiler(qc:QuantumCircuit|list|str,chip_name:str,compile:bool,
96
96
  quarkQC_compiled = SabreRouting(subgraph,initial_mapping='trivial',do_random_choice=False,iterations=5).run(quarkQC)
97
97
  else:
98
98
  raise(ValueError('More optimize_level is not support now!'))
99
-
99
+
100
100
  quarkQC_half_compiled = copy.deepcopy(quarkQC_compiled)
101
101
  quarkQC_half_compiled = TranslateToBasisGates(convert_single_qubit_gate_to_u=False,two_qubit_gate_basis='cx').run(quarkQC_half_compiled)
102
102
  quarkQC_half_compiled = GateCompressor().run(quarkQC_half_compiled)
@@ -144,7 +144,7 @@ def call_quark_transpiler(qc:QuantumCircuit|list|str,chip_name:str,compile:bool,
144
144
 
145
145
  # check CZ
146
146
  ncz = quarkQC_compiled.ncz
147
- if ncz > 100:
147
+ if ncz > 200:
148
148
  raise(ValueError(f'The number of two-qubit gates in the circuit is {ncz} exceeds 100.'))
149
149
 
150
150
  if return_qlisp:
@@ -34,6 +34,7 @@ from .decompose import (cx_decompose,
34
34
  rxx_decompose,
35
35
  ryy_decompose,
36
36
  rzz_decompose,
37
+ cp_decompose,
37
38
  u3_decompose,
38
39
  )
39
40
  from .basepasses import TranspilerPass
@@ -114,6 +115,8 @@ class TranslateToBasisGates(TranspilerPass):
114
115
  new += ryy_decompose(*gate_info[1:],self.convert_single_qubit_gate_to_u,self.two_qubit_gate_basis)
115
116
  elif gate == 'rzz':
116
117
  new += rzz_decompose(*gate_info[1:],self.convert_single_qubit_gate_to_u,self.two_qubit_gate_basis)
118
+ elif gate == 'cp':
119
+ new += cp_decompose(*gate_info[1:],self.convert_single_qubit_gate_to_u)
117
120
  elif gate in functional_gates_available.keys():
118
121
  new.append(gate_info)
119
122
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quarkcircuit
3
- Version: 0.3.0.dev2
3
+ Version: 0.3.1
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