Sequential Quantum Gate Decomposer  v1.9.6
Powerful decomposition of general unitarias into one- and two-qubit gates gates
continuity.py
Go to the documentation of this file.
1 """Phase-2 continuity VQE builders for partitioning API tests (mirrors benchmarks planner_surface.common)."""
2 
3 from __future__ import annotations
4 
5 import sys
6 
7 import numpy as np
8 import scipy as sp
9 
10 from squander import Variational_Quantum_Eigensolver
11 
12 
13 SIGMA_X = sp.sparse.csr_matrix(np.array([[0, 1], [1, 0]], dtype=np.complex128))
14 SIGMA_Y = sp.sparse.csr_matrix(np.array([[0, -1j], [1j, 0]], dtype=np.complex128))
15 SIGMA_Z = sp.sparse.csr_matrix(np.array([[1, 0], [0, -1]], dtype=np.complex128))
16 
17 DEFAULT_ANSATZ = "HEA"
18 DEFAULT_LAYERS = 1
19 DEFAULT_INNER_BLOCKS = 1
20 PRIMARY_BACKEND = "density_matrix"
21 
22 
23 def build_open_chain_topology(qbit_num: int) -> list[tuple[int, int]]:
24  return [(index, index + 1) for index in range(qbit_num - 1)]
25 
26 
28  n_qubits: int, target: int, pauli: sp.sparse.csr_matrix
29 ) -> sp.sparse.csr_matrix:
30  result = None
31  for qubit in range(n_qubits):
32  factor = pauli if qubit == target else sp.sparse.eye(2, format="csr")
33  result = factor if result is None else sp.sparse.kron(result, factor, format="csr")
34  return result.tocsr()
35 
36 
37 def _two_pauli_term(
38  n_qubits: int,
39  first: int,
40  second: int,
41  pauli: sp.sparse.csr_matrix,
42 ) -> sp.sparse.csr_matrix:
43  result = None
44  for qubit in range(n_qubits):
45  factor = pauli if qubit in {first, second} else sp.sparse.eye(2, format="csr")
46  result = factor if result is None else sp.sparse.kron(result, factor, format="csr")
47  return result.tocsr()
48 
49 
51  n_qubits: int,
52  *,
53  topology: list[tuple[int, int]] | None = None,
54  h: float = 0.5,
55  jx: float = 1.0,
56  jy: float = 1.0,
57  jz: float = 1.0,
58 ) -> sp.sparse.csr_matrix:
59  if topology is None:
60  topology = build_open_chain_topology(n_qubits)
61 
62  hamiltonian = sp.sparse.csr_matrix(
63  (2**n_qubits, 2**n_qubits), dtype=np.complex128
64  )
65 
66  for control, target in topology:
67  hamiltonian += -0.5 * jx * _two_pauli_term(n_qubits, control, target, SIGMA_X)
68  hamiltonian += -0.5 * jy * _two_pauli_term(n_qubits, control, target, SIGMA_Y)
69  hamiltonian += -0.5 * jz * _two_pauli_term(n_qubits, control, target, SIGMA_Z)
70 
71  for qubit in range(n_qubits):
72  hamiltonian += -0.5 * h * _single_pauli_term(n_qubits, qubit, SIGMA_Z)
73 
74  return hamiltonian.tocsr()
75 
76 
77 def build_continuity_density_noise() -> list[dict]:
78  return [
79  {
80  "channel": "local_depolarizing",
81  "target": 0,
82  "after_gate_index": 0,
83  "error_rate": 0.1,
84  },
85  {
86  "channel": "amplitude_damping",
87  "target": 1,
88  "after_gate_index": 2,
89  "gamma": 0.05,
90  },
91  {
92  "channel": "phase_damping",
93  "target": 0,
94  "after_gate_index": 4,
95  "lambda": 0.07,
96  },
97  ]
98 
99 
101  return {
102  "max_inner_iterations": 4,
103  "max_iterations": 1,
104  "convergence_length": 2,
105  }
106 
107 
108 def build_case_metadata(*, qbit_num: int, topology, density_noise) -> dict:
109  return {
110  "backend": PRIMARY_BACKEND,
111  "qbit_num": qbit_num,
112  "topology": list(topology),
113  "ansatz": DEFAULT_ANSATZ,
114  "layers": DEFAULT_LAYERS,
115  "inner_blocks": DEFAULT_INNER_BLOCKS,
116  "density_noise": [dict(item) for item in density_noise],
117  }
118 
119 
121  return {
122  "python": sys.version.split()[0],
123  "numpy": np.__version__,
124  "scipy": sp.__version__,
125  }
126 
127 
129  qbit_num: int,
130  *,
131  density_noise: list[dict] | None = None,
132 ):
133  requested_density_noise = (
135  if density_noise is None
136  else [dict(item) for item in density_noise]
137  )
138  topology = build_open_chain_topology(qbit_num)
139  hamiltonian = build_xxz_hamiltonian(qbit_num, topology=topology)
140  vqe = Variational_Quantum_Eigensolver(
141  hamiltonian,
142  qbit_num,
144  backend=PRIMARY_BACKEND,
145  density_noise=requested_density_noise,
146  )
147  vqe.set_Ansatz(DEFAULT_ANSATZ)
148  vqe.Generate_Circuit(layers=DEFAULT_LAYERS, inner_blocks=DEFAULT_INNER_BLOCKS)
149  return vqe, hamiltonian, topology