|
13 | 13 | """
|
14 | 14 | RB Helper functions
|
15 | 15 | """
|
| 16 | +import functools |
| 17 | +import operator |
16 | 18 | from typing import Tuple, Dict, Optional, List, Union, Sequence
|
17 | 19 |
|
18 | 20 | import numpy as np
|
19 | 21 | import uncertainties
|
| 22 | + |
| 23 | +import qiskit.quantum_info as qi |
20 | 24 | from qiskit import QiskitError, QuantumCircuit
|
21 | 25 | from qiskit.providers.backend import Backend
|
22 |
| - |
23 | 26 | from qiskit_experiments.database_service.device_component import Qubit
|
24 | 27 | from qiskit_experiments.framework import DbAnalysisResultV1, AnalysisResultData
|
25 | 28 | from qiskit_experiments.warnings import deprecated_function
|
@@ -138,6 +141,10 @@ def gates_per_clifford(
|
138 | 141 | return {key: value[0] / value[1] for (key, value) in result.items()}
|
139 | 142 |
|
140 | 143 | @staticmethod
|
| 144 | + @deprecated_function( |
| 145 | + last_version="0.4", |
| 146 | + msg="Please use coherence_limit_error function that can handle three or more qubits instead.", |
| 147 | + ) |
141 | 148 | def coherence_limit(nQ=2, T1_list=None, T2_list=None, gatelen=0.1):
|
142 | 149 | """
|
143 | 150 | The error per gate (1-average_gate_fidelity) given by the T1,T2 limit.
|
@@ -199,6 +206,79 @@ def coherence_limit(nQ=2, T1_list=None, T2_list=None, gatelen=0.1):
|
199 | 206 |
|
200 | 207 | return coherence_limit_err
|
201 | 208 |
|
| 209 | + @staticmethod |
| 210 | + def coherence_limit_error( |
| 211 | + num_qubits: int, gate_length: float, t1s: Sequence, t2s: Optional[Sequence] = None |
| 212 | + ): |
| 213 | + r""" |
| 214 | + The error per gate (1 - average_gate_fidelity) given by the T1,T2 limit |
| 215 | + assuming qubit-wise gate-independent amplitude damping error |
| 216 | + (or thermal relaxation error with no excitation). |
| 217 | +
|
| 218 | + That means, suppose the gate length $t$, the Choi matrix of the amplitude damping channel |
| 219 | + $\Lambda_q$ for a single qubit $q$ with $T_1$ and $T_2$ is give by |
| 220 | + $$ |
| 221 | + \begin{bmatrix} |
| 222 | + 1 & 0 & 0 & e^{-\frac{t}{T_2}} \\ |
| 223 | + 0 & 0 & 0 & 0 \\ |
| 224 | + 0 & 0 & 1-e^{-\frac{t}{T_1}} & 0 \\ |
| 225 | + e^{-\frac{t}{T_2}} & 0 & 0 & e^{-\frac{t}{T_1}} \\ |
| 226 | + \end{bmatrix} |
| 227 | + $$. |
| 228 | + The coherence limit error computed by this function is $1 - F_{\text{ave}}(\mathcal{E}, U)$ |
| 229 | + where |
| 230 | + And the following equality holds. |
| 231 | + $$ |
| 232 | + \begin{align} |
| 233 | + 1 - F_{\text{ave}}(\mathcal{E}, U) |
| 234 | + &= \frac{d}{d+1} \left(1 - F_{\text{pro}}(\mathcal{E}, U)\right) \\ |
| 235 | + &= \frac{d}{d+1} \left(1 - \frac{Tr[S_U^\dagger S_{\mathcal{E}}]}{d^2}\right) \\ |
| 236 | + &= \frac{d}{d+1} \left(1 - \frac{Tr[S_{\Lambda}]}{d^2}\right) |
| 237 | + \end{align} |
| 238 | + $$ |
| 239 | + where $F_{\text{avg}}(\mathcal{E}, U)$ and $F_{\text{pro}}(\mathcal{E}, U)$ are |
| 240 | + the average gate fidelity and the process fidelity of a quantum channel $\mathcal{E}$ |
| 241 | + with a target unitary $U$, respectively, and $d$ is the dimension of Hilbert space of |
| 242 | + the considering qubit system. |
| 243 | +
|
| 244 | + Args: |
| 245 | + num_qubits: Number of qubits. |
| 246 | + gate_length: Duration of the gate in seconds. |
| 247 | + t1s: List of T1's from qubit 0 to num_qubits-1. |
| 248 | + t2s: List of T2's (as measured, not Tphi). If not given, assume T2 = 2 * T1. |
| 249 | + Each T2 value is truncated down to 2 * T1 if T2 > 2 * T1. |
| 250 | +
|
| 251 | + Returns: |
| 252 | + float: coherence limited error per gate. |
| 253 | + Raises: |
| 254 | + ValueError: if there are invalid inputs |
| 255 | + """ |
| 256 | + t1s = np.array(t1s) |
| 257 | + if t2s is None: |
| 258 | + t2s = 2 * t1s |
| 259 | + else: |
| 260 | + t2s = np.array([min(t2, 2 * t1) for t1, t2 in zip(t1s, t2s)]) |
| 261 | + |
| 262 | + if len(t1s) != num_qubits or len(t2s) != num_qubits: |
| 263 | + raise ValueError("Length of t1s/t2s must equal num_qubits") |
| 264 | + |
| 265 | + def amplitude_damping_choi(t1, t2, time): |
| 266 | + return qi.Choi( |
| 267 | + np.array( |
| 268 | + [ |
| 269 | + [1, 0, 0, np.exp(-time / t2)], |
| 270 | + [0, 0, 0, 0], |
| 271 | + [0, 0, 1 - np.exp(-time / t1), 0], |
| 272 | + [np.exp(-time / t2), 0, 0, np.exp(-time / t1)], |
| 273 | + ] |
| 274 | + ) |
| 275 | + ) |
| 276 | + |
| 277 | + chois = [amplitude_damping_choi(t1, t2, gate_length) for t1, t2 in zip(t1s, t2s)] |
| 278 | + traces = [np.real(np.trace(np.array(qi.SuperOp(choi)))) for choi in chois] |
| 279 | + d = 2**num_qubits |
| 280 | + return d / (d + 1) * (1 - functools.reduce(operator.mul, traces) / (d * d)) |
| 281 | + |
202 | 282 | @staticmethod
|
203 | 283 | @deprecated_function(
|
204 | 284 | last_version="0.4",
|
|
0 commit comments