"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"qv_circs_nomeas[0][0].draw(fold=-1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Step 2: Simulate the ideal QV circuits\n",
"\n",
"The quantum volume method requires that we know the ideal output for each circuit, so we use the Aer simulator to get the ideal result."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Simulated trial 100/100\n"
]
}
],
"source": [
"sv_sim = qiskit.Aer.get_backend('aer_simulator')\n",
"ideal_results = []\n",
"for trial in range(ntrials):\n",
" clear_output(wait=True)\n",
" for qc in qv_circs_nomeas[trial]:\n",
" qc.save_statevector()\n",
" result = qiskit.execute(qv_circs_nomeas[trial], backend=sv_sim).result()\n",
" ideal_results.append(result)\n",
" print(f'Simulated trial {trial+1}/{ntrials}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we load the ideal results into a quantum volume fitter"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"qv_fitter = qv.QVFitter(qubit_lists=qubit_lists)\n",
"qv_fitter.add_statevectors(ideal_results)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Step 3: Calculate the heavy outputs\n",
"\n",
"To define when a model circuit $U$ has been successfully implemented in practice, we use the *heavy output* generation problem. The ideal output distribution is $p_U(x) = |\\langle x|U|0 \\rangle|^2$, \n",
"where $x \\in \\{0,1\\}^m$ is an observable bit-string. \n",
"\n",
"Consider the set of output probabilities given by the range of $p_U(x)$ sorted in ascending order \n",
"$p_0 \\leq p_1 \\leq \\dots \\leq p_{2^m-1}$. The median of the set of probabilities is \n",
"$p_{med} = (p_{2^{m-1}} + p_{2^{m-1}-1})/2$, and the *heavy outputs* are\n",
"\n",
"\n",
"$$ H_U = \\{ x \\in \\{0,1\\}^m \\text{ such that } p_U(x)>p_{med} \\}.$$\n",
"\n",
"\n",
"The heavy output generation problem is to produce a set of output strings such that more than two-thirds are heavy.\n",
"\n",
"As an illustration, we print the heavy outputs from various depths and their probabilities (for trial 0):"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"qv_depth_3_trial_0: ['000', '001', '010', '100']\n",
"qv_depth_4_trial_0: ['0010', '0011', '0100', '0101', '0110', '1001', '1011', '1110']\n",
"qv_depth_5_trial_0: ['00010', '00011', '00100', '00101', '00110', '00111', '01011', '01100', '01101', '01110', '01111', '10000', '11001', '11011', '11110', '11111']\n",
"qv_depth_6_trial_0: ['000000', '000001', '000011', '000100', '001000', '001010', '001111', '010000', '010010', '010011', '010100', '010110', '011110', '100000', '100010', '100011', '100100', '100110', '101001', '101010', '101111', '110000', '110001', '110010', '110100', '110110', '110111', '111000', '111001', '111011', '111100', '111110']\n"
]
}
],
"source": [
"for qubit_list in qubit_lists:\n",
" l = len(qubit_list)\n",
" print ('qv_depth_'+str(l)+'_trial_0:', qv_fitter._heavy_outputs['qv_depth_'+str(l)+'_trial_0'])"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"qv_depth_3_trial_0: 0.8655813834341206\n",
"qv_depth_4_trial_0: 0.8875227654224885\n",
"qv_depth_5_trial_0: 0.8543419735543125\n",
"qv_depth_6_trial_0: 0.8661188949571332\n"
]
}
],
"source": [
"for qubit_list in qubit_lists:\n",
" l = len(qubit_list)\n",
" print ('qv_depth_'+str(l)+'_trial_0:', qv_fitter._heavy_output_prob_ideal['qv_depth_'+str(l)+'_trial_0'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Step 4: Define the noise model\n",
"\n",
"We define a noise model for the simulator. To simulate decay, we add depolarizing error probabilities to the CNOT and U gates."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"noise_model = NoiseModel()\n",
"p1Q = 0.002\n",
"p2Q = 0.02\n",
"noise_model.add_all_qubit_quantum_error(depolarizing_error(p1Q, 1), 'u2')\n",
"noise_model.add_all_qubit_quantum_error(depolarizing_error(2*p1Q, 1), 'u3')\n",
"noise_model.add_all_qubit_quantum_error(depolarizing_error(p2Q, 2), 'cx')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can execute the QV sequences either using Qiskit Aer Simulator (with some noise model) or using IBMQ provider, and obtain a list of exp_results."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Completed trial 100/100\n"
]
}
],
"source": [
"aer_sim = qiskit.Aer.get_backend('aer_simulator')\n",
"basis_gates = ['u1','u2','u3','cx'] # use U,CX for now\n",
"shots = 1024\n",
"exp_results = []\n",
"for trial in range(ntrials):\n",
" clear_output(wait=True)\n",
" t_qcs = transpile(qv_circs[trial], basis_gates=basis_gates, optimization_level=3)\n",
" qobj = assemble(t_qcs)\n",
" result = aer_sim.run(qobj, noise_model=noise_model, max_parallel_experiments=0).result()\n",
" exp_results.append(result)\n",
" print(f'Completed trial {trial+1}/{ntrials}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Step 5: Calculate the average gate fidelity\n",
"\n",
"The *average gate fidelity* between the $m$-qubit ideal unitaries $U$ and the executed $U'$ is:\n",
"\n",
"\n",
"$$ F_{avg}(U,U') = \\frac{|Tr(U^{\\dagger}U')|^2/2^m+1}{2^m+1}$$\n",
"\n",
"\n",
"\n",
"The observed distribution for an implementation $U'$ of model circuit $U$ is $q_U(x)$, and the probability of sampling\n",
"a heavy output is:\n",
"\n",
"\n",
"$$ h_U = \\sum_{x \\in H_U} q_U(x)$$\n",
"\n",
"\n",
"\n",
"As an illustration, we print the heavy output counts from various depths (for trial 0):"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"qv_depth_3_trial_0: 828\n",
"qv_depth_4_trial_0: 839\n",
"qv_depth_5_trial_0: 768\n",
"qv_depth_6_trial_0: 694\n"
]
}
],
"source": [
"qv_fitter.add_data(exp_results)\n",
"for qubit_list in qubit_lists:\n",
" l = len(qubit_list)\n",
" print ('qv_depth_'+str(l)+'_trial_0:', qv_fitter._heavy_output_counts['qv_depth_'+str(l)+'_trial_0'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Step 6: Calculate the achievable depth\n",
"\n",
"The probability of observing a heavy output by implementing a randomly selected depth $d$ model circuit is:\n",
"\n",
"\n",
"$$h_d = \\int_U h_U dU$$\n",
"\n",
"\n",
"\n",
"The *achievable depth* $d(m)$ is the largest $d$ such that we are confident that $h_d > 2/3$. In other words,\n",
"\n",
"\n",
"$$ h_1,h_2,\\dots,h_{d(m)}>2/3 \\text{ and } h_{d(m)+1} \\leq 2/3$$\n",
"\n",
"\n",
"\n",
"We now convert the heavy outputs in the different trials and calculate the mean $h_d$ and the error for plotting the graph."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n",
"\n"
],
"text/plain": [
"

"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=(10, 6))\n",
"ax = plt.gca()\n",
"\n",
"# Plot the essence by calling plot_rb_data\n",
"qv_fitter.plot_qv_data(ax=ax, show_plt=False)\n",
"\n",
"# Add title and label\n",
"ax.set_title('Quantum Volume for up to %d Qubits \\n and %d Trials'%(len(qubit_lists[-1]), ntrials), fontsize=18)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Step 7: Calculate the Quantum Volume\n",
"\n",
"\n",
"The quantum volume treats the width and depth of a model circuit with equal importance and measures the largest square-shaped (i.e., $m = d$) model circuit a quantum computer can implement successfully on average. \n",
"\n",
"The *quantum volume* $V_Q$ is defined as\n",
"\n",
"\n",
"$$\\log_2 V_Q = \\arg\\max_{m} \\min (m, d(m))$$\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We list the statistics for each depth. For each depth we list if the depth was successful or not and with what confidence interval. For a depth to be successful the confidence interval must be > 97.5%."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Width/depth 3 greater than 2/3 (0.790439) with confidence 0.998822 (successful). Quantum volume 8\n",
"Width/depth 4 greater than 2/3 (0.733740) with confidence 0.935429 (unsuccessful).\n",
"Width/depth 5 greater than 2/3 (0.731826) with confidence 0.929333 (unsuccessful).\n",
"Width/depth 6 less than 2/3 (unsuccessful).\n"
]
}
],
"source": [
"qv_success_list = qv_fitter.qv_success()\n",
"qv_list = qv_fitter.ydata\n",
"QV = 1\n",
"for qidx, qubit_list in enumerate(qubit_lists):\n",
" if qv_list[0][qidx]>2/3:\n",
" if qv_success_list[qidx][0]:\n",
" print(\"Width/depth %d greater than 2/3 (%f) with confidence %f (successful). Quantum volume %d\"%\n",
" (len(qubit_list),qv_list[0][qidx],qv_success_list[qidx][1],qv_fitter.quantum_volume()[qidx]))\n",
" QV = qv_fitter.quantum_volume()[qidx]\n",
" else:\n",
" print(\"Width/depth %d greater than 2/3 (%f) with confidence %f (unsuccessful).\"%\n",
" (len(qubit_list),qv_list[0][qidx],qv_success_list[qidx][1]))\n",
" else:\n",
" print(\"Width/depth %d less than 2/3 (unsuccessful).\"%len(qubit_list))"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The Quantum Volume is: 8\n"
]
}
],
"source": [
"print (\"The Quantum Volume is:\", QV) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### References\n",
"\n",
"[1] Andrew W. Cross, Lev S. Bishop, Sarah Sheldon, Paul D. Nation, and Jay M. Gambetta, *Validating quantum computers using randomized model circuits*, Phys. Rev. A **100**, 032328 (2019). https://arxiv.org/pdf/1811.12926"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"### Version Information

"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import qiskit.tools.jupyter\n",
"%qiskit_version_table"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.7"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

Qiskit Software | Version |
---|---|

Qiskit | 0.27.0 |

Terra | 0.17.4 |

Aer | 0.8.2 |

Ignis | 0.6.0 |

Aqua | 0.9.2 |

IBM Q Provider | 0.14.0 |

System information | |

Python | 3.7.7 (default, May 6 2020, 04:59:01) \n", "[Clang 4.0.1 (tags/RELEASE_401/final)] |

OS | Darwin |

CPUs | 8 |

Memory (Gb) | 32.0 |

Thu Jun 17 16:25:25 2021 BST |