Skip to content

Commit

Permalink
Add QV tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
nonhermitian committed Sep 3, 2021
1 parent 656cf9e commit 3b9811a
Showing 1 changed file with 281 additions and 0 deletions.
281 changes: 281 additions & 0 deletions tutorials/03_qv_example.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "54191476",
"metadata": {},
"source": [
"# Quantum Volume\n",
"\n",
"Here we show off using the expectation value functionality of the M3 distribution classes using Quantum Volume (QV) as an example. Here we formulate QV as an expectation value of a projector onto the heavy-output elements on a distribution."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "c1b69009",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from qiskit import *\n",
"from qiskit.quantum_info import Statevector\n",
"from qiskit.circuit.library import QuantumVolume\n",
"import mthree"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "cdd59933",
"metadata": {},
"outputs": [],
"source": [
"from qiskit.test.mock import FakeAthens\n",
"noisy_sim = FakeAthens()"
]
},
{
"cell_type": "markdown",
"id": "0118fe34",
"metadata": {},
"source": [
"QV is defined in terms of heavy-ouputs of a distribution. Heavy-outputs are those bit-strings that are those that have probabilities above the median value of the distribution. Below we define the projection operator onto the set of bit-strings that are heavy-outputs for a given distribution."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "ccf57f8b",
"metadata": {},
"outputs": [],
"source": [
"def heavy_projector(qv_probs):\n",
" \"\"\"Forms the projection operator onto the heavy-outputs of a given probability distribution.\n",
" \n",
" Parameters:\n",
" qv_probs (dict): A dictionary of bitstrings and associated probabilities.\n",
" \n",
" Returns:\n",
" dict: Projector onto the heavy-set.\n",
" \"\"\"\n",
" median_prob = np.median(list(qv_probs.values()))\n",
" heavy_strs = {}\n",
" for key, val in qv_probs.items():\n",
" if val > median_prob:\n",
" heavy_strs[key] = 1\n",
" return heavy_strs"
]
},
{
"cell_type": "markdown",
"id": "2134ff49",
"metadata": {},
"source": [
"First we begin by calibrating our M3 mitigator over all the qubits on our noisy simulator. (We use the `independent` method since it is much faster to do so on a simulator.)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "254a4dbe",
"metadata": {},
"outputs": [],
"source": [
"mit = mthree.M3Mitigation(noisy_sim)\n",
"mit.cals_from_system(method='independent')"
]
},
{
"cell_type": "markdown",
"id": "1b267a08",
"metadata": {},
"source": [
"Now we generate 10 QV circuits as our dataset."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "2db632a1",
"metadata": {},
"outputs": [],
"source": [
"# Generate QV circuits\n",
"N = 10\n",
"qv_circs = [QuantumVolume(5) for _ in range(N)]"
]
},
{
"cell_type": "markdown",
"id": "e0698f04",
"metadata": {},
"source": [
"Next, we have to determine the heavy-set of each circuit from the ideal answer, and then pass this along to our heavy-set projector function that we defined above."
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "911f8110",
"metadata": {},
"outputs": [],
"source": [
"# Compute ideal distributions and projectors on the heavy set.\n",
"ideal_probs = [Statevector.from_instruction(circ).probabilities_dict() for circ in qv_circs]\n",
"heavy_projectors = [heavy_projector(probs) for probs in ideal_probs]"
]
},
{
"cell_type": "markdown",
"id": "f45f1074",
"metadata": {},
"source": [
"Now, in preparation for actual execution, we add measurements to the end of our QV circuits, and compile them for the target device"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "87e116f2",
"metadata": {},
"outputs": [],
"source": [
"# Add meauserements to circuits and transpile\n",
"trans_circs = transpile([circ.measure_all(inplace=False) for circ in qv_circs], noisy_sim,\n",
" layout_method='sabre', routing_method='sabre', optimization_level=3)"
]
},
{
"cell_type": "markdown",
"id": "460e1859",
"metadata": {},
"source": [
"Because the SWAP mapping of the circuit permutes the qubit states, we need the final measurement mapping for each circuit to know which physical qubit corresponds to each measured bit:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "f2b71415",
"metadata": {},
"outputs": [],
"source": [
"# Determine final qubit mappings\n",
"qubits = [list(mthree.utils.final_measurement_mapping(circ)) for circ in trans_circs]"
]
},
{
"cell_type": "markdown",
"id": "5257a761",
"metadata": {},
"source": [
"We are now ready to execute the circuits on the target backend, and mitigate the resulting raw counts:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "39b5d818",
"metadata": {},
"outputs": [],
"source": [
"# Execute circuits and mitigate\n",
"raw_counts = noisy_sim.run(trans_circs, shots=8192).result().get_counts()\n",
"quasi_collection = mit.apply_correction(raw_counts, qubits)"
]
},
{
"cell_type": "markdown",
"id": "32b82cd1",
"metadata": {},
"source": [
"The value needed to determine if each circuit represents a passing QV value is determined by the expectation value of the heavy projector for each circuit:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "b8136595",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([0.64273103, 0.73990926, 0.7367156 , 0.68290608, 0.7421638 ,\n",
" 0.66162356, 0.70204107, 0.67630205, 0.73943566, 0.73140044])"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Determine expectation value of heavy set prjector\n",
"expvals = quasi_collection.expval(heavy_projectors)\n",
"expvals"
]
},
{
"cell_type": "markdown",
"id": "42880efe",
"metadata": {},
"source": [
"A passing QV score is one where the expectation value is above 2/3:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "ac23ea82",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([False, True, True, True, True, False, True, True, True,\n",
" True])"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Check if the scores are passing or not\n",
"expvals > 2/3"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "93b1ff8d",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.9.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

0 comments on commit 3b9811a

Please sign in to comment.