{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Running Multiple Randomized Benchmarking Experiments" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This tutorial shows how to easily run multiple RB experiments concurrently. This includes running RB on different subsets of a device, as well as running [simultaneous RB]() experiments. Here we'll demonstrate generating an experiment to run 1, 2, 3 and 4 qubit RB in sequence (i.e., separately), as well as running 1-qubit RB in parallel on all the qubits (i.e., simultaneously).\n", "\n", "Note that this functionality is not specific to RB: similar code could be used to combine multiple GST experiments, or GST and RB experiments, etc." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/tjproct/.pyenv/versions/3.7.4/lib/python3.7/site-packages/pandas/compat/__init__.py:85: UserWarning: Could not import the lzma module. Your installed Python is incomplete. Attempting to use lzma compression will result in a RuntimeError.\n", " warnings.warn(msg)\n", "/Users/tjproct/.pyenv/versions/3.7.4/lib/python3.7/site-packages/pandas/compat/__init__.py:85: UserWarning: Could not import the lzma module. Your installed Python is incomplete. Attempting to use lzma compression will result in a RuntimeError.\n", " warnings.warn(msg)\n" ] } ], "source": [ "import pygsti\n", "from pygsti.processors import QubitProcessorSpec as QPS\n", "from pygsti.processors import CliffordCompilationRules as CCR" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's define the layout and gates of a 4-qubit device that we want to do this experiment on." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "n_qubits = 4\n", "qubit_labels = ['Q'+str(i) for i in range(n_qubits)]\n", "gate_names = ['Gc{}'.format(i) for i in range(24)] + ['Gcnot'] \n", "pspec = QPS(n_qubits, gate_names, qubit_labels=qubit_labels, geometry='ring')\n", "\n", "compilations = {'absolute': CCR.create_standard(pspec, 'absolute', ('paulis', '1Qcliffords'), verbosity=0), \n", " 'paulieq': CCR.create_standard(pspec, 'paulieq', ('1Qcliffords', 'allcnots'), verbosity=0)}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now let's generate the separate 1-4 qubit RB experiments. We'll run Mirror RB, but this works for all types of RB." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "- Sampling 10 circuits at MRB length 0 (1 of 10 depths) with seed 386582\n", "- Sampling 10 circuits at MRB length 2 (2 of 10 depths) with seed 386592\n", "- Sampling 10 circuits at MRB length 4 (3 of 10 depths) with seed 386602\n", "- Sampling 10 circuits at MRB length 8 (4 of 10 depths) with seed 386612\n", "- Sampling 10 circuits at MRB length 16 (5 of 10 depths) with seed 386622\n", "- Sampling 10 circuits at MRB length 32 (6 of 10 depths) with seed 386632\n", "- Sampling 10 circuits at MRB length 64 (7 of 10 depths) with seed 386642\n", "- Sampling 10 circuits at MRB length 128 (8 of 10 depths) with seed 386652\n", "- Sampling 10 circuits at MRB length 256 (9 of 10 depths) with seed 386662\n", "- Sampling 10 circuits at MRB length 512 (10 of 10 depths) with seed 386672\n", "- Sampling 10 circuits at MRB length 0 (1 of 8 depths) with seed 554178\n", "- Sampling 10 circuits at MRB length 2 (2 of 8 depths) with seed 554188\n", "- Sampling 10 circuits at MRB length 4 (3 of 8 depths) with seed 554198\n", "- Sampling 10 circuits at MRB length 8 (4 of 8 depths) with seed 554208\n", "- Sampling 10 circuits at MRB length 16 (5 of 8 depths) with seed 554218\n", "- Sampling 10 circuits at MRB length 32 (6 of 8 depths) with seed 554228\n", "- Sampling 10 circuits at MRB length 64 (7 of 8 depths) with seed 554238\n", "- Sampling 10 circuits at MRB length 128 (8 of 8 depths) with seed 554248\n", "- Sampling 10 circuits at MRB length 0 (1 of 7 depths) with seed 857212\n", "- Sampling 10 circuits at MRB length 2 (2 of 7 depths) with seed 857222\n", "- Sampling 10 circuits at MRB length 4 (3 of 7 depths) with seed 857232\n", "- Sampling 10 circuits at MRB length 8 (4 of 7 depths) with seed 857242\n", "- Sampling 10 circuits at MRB length 16 (5 of 7 depths) with seed 857252\n", "- Sampling 10 circuits at MRB length 32 (6 of 7 depths) with seed 857262\n", "- Sampling 10 circuits at MRB length 64 (7 of 7 depths) with seed 857272\n", "- Sampling 10 circuits at MRB length 0 (1 of 6 depths) with seed 865565\n", "- Sampling 10 circuits at MRB length 2 (2 of 6 depths) with seed 865575\n", "- Sampling 10 circuits at MRB length 4 (3 of 6 depths) with seed 865585\n", "- Sampling 10 circuits at MRB length 8 (4 of 6 depths) with seed 865595\n", "- Sampling 10 circuits at MRB length 16 (5 of 6 depths) with seed 865605\n", "- Sampling 10 circuits at MRB length 32 (6 of 6 depths) with seed 865615\n" ] } ], "source": [ "# The qubit sets of each size to benchmark, and sampling details.\n", "qubits = {1: ['Q0',], 2:['Q0','Q1'], 3:['Q0','Q1','Q2'], 4:['Q0','Q1','Q2', 'Q3']}\n", "# The depths for the different number of qubits.\n", "depths = {1: [0, 2, 4, 8, 16, 32, 64, 128, 256, 512],\n", " 2: [0, 2, 4, 8, 16, 32, 64, 128],\n", " 3: [0, 2, 4, 8, 16, 32, 64],\n", " 4: [0, 2, 4, 8, 16, 32]}\n", "\n", "# This loops through an generates the experiment design for each case.\n", "designs = {}\n", "for n in [1,2,3,4]:\n", " \n", " designs[str(n)+'Q-RB'] = pygsti.protocols.MirrorRBDesign(pspec, depths[n], 10, qubit_labels=qubits[n],\n", " clifford_compilations=compilations,\n", " sampler='edgegrab', samplerargs=[0.5],\n", " add_default_protocol=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we generate the simultaneous 1-qubit RB experiment. We do this by constructing each of the 1-qubit experiment designs, and then combining them together in a `SimultaneousExperimentDesign`." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "- Sampling 10 circuits at MRB length 0 (1 of 10 depths) with seed 875900\n", "- Sampling 10 circuits at MRB length 2 (2 of 10 depths) with seed 875910\n", "- Sampling 10 circuits at MRB length 4 (3 of 10 depths) with seed 875920\n", "- Sampling 10 circuits at MRB length 8 (4 of 10 depths) with seed 875930\n", "- Sampling 10 circuits at MRB length 16 (5 of 10 depths) with seed 875940\n", "- Sampling 10 circuits at MRB length 32 (6 of 10 depths) with seed 875950\n", "- Sampling 10 circuits at MRB length 64 (7 of 10 depths) with seed 875960\n", "- Sampling 10 circuits at MRB length 128 (8 of 10 depths) with seed 875970\n", "- Sampling 10 circuits at MRB length 256 (9 of 10 depths) with seed 875980\n", "- Sampling 10 circuits at MRB length 512 (10 of 10 depths) with seed 875990\n", "- Sampling 10 circuits at MRB length 0 (1 of 10 depths) with seed 71217\n", "- Sampling 10 circuits at MRB length 2 (2 of 10 depths) with seed 71227\n", "- Sampling 10 circuits at MRB length 4 (3 of 10 depths) with seed 71237\n", "- Sampling 10 circuits at MRB length 8 (4 of 10 depths) with seed 71247\n", "- Sampling 10 circuits at MRB length 16 (5 of 10 depths) with seed 71257\n", "- Sampling 10 circuits at MRB length 32 (6 of 10 depths) with seed 71267\n", "- Sampling 10 circuits at MRB length 64 (7 of 10 depths) with seed 71277\n", "- Sampling 10 circuits at MRB length 128 (8 of 10 depths) with seed 71287\n", "- Sampling 10 circuits at MRB length 256 (9 of 10 depths) with seed 71297\n", "- Sampling 10 circuits at MRB length 512 (10 of 10 depths) with seed 71307\n", "- Sampling 10 circuits at MRB length 0 (1 of 10 depths) with seed 155657\n", "- Sampling 10 circuits at MRB length 2 (2 of 10 depths) with seed 155667\n", "- Sampling 10 circuits at MRB length 4 (3 of 10 depths) with seed 155677\n", "- Sampling 10 circuits at MRB length 8 (4 of 10 depths) with seed 155687\n", "- Sampling 10 circuits at MRB length 16 (5 of 10 depths) with seed 155697\n", "- Sampling 10 circuits at MRB length 32 (6 of 10 depths) with seed 155707\n", "- Sampling 10 circuits at MRB length 64 (7 of 10 depths) with seed 155717\n", "- Sampling 10 circuits at MRB length 128 (8 of 10 depths) with seed 155727\n", "- Sampling 10 circuits at MRB length 256 (9 of 10 depths) with seed 155737\n", "- Sampling 10 circuits at MRB length 512 (10 of 10 depths) with seed 155747\n", "- Sampling 10 circuits at MRB length 0 (1 of 10 depths) with seed 492081\n", "- Sampling 10 circuits at MRB length 2 (2 of 10 depths) with seed 492091\n", "- Sampling 10 circuits at MRB length 4 (3 of 10 depths) with seed 492101\n", "- Sampling 10 circuits at MRB length 8 (4 of 10 depths) with seed 492111\n", "- Sampling 10 circuits at MRB length 16 (5 of 10 depths) with seed 492121\n", "- Sampling 10 circuits at MRB length 32 (6 of 10 depths) with seed 492131\n", "- Sampling 10 circuits at MRB length 64 (7 of 10 depths) with seed 492141\n", "- Sampling 10 circuits at MRB length 128 (8 of 10 depths) with seed 492151\n", "- Sampling 10 circuits at MRB length 256 (9 of 10 depths) with seed 492161\n", "- Sampling 10 circuits at MRB length 512 (10 of 10 depths) with seed 492171\n" ] } ], "source": [ "oneQdesigns = []\n", "for q in qubit_labels:\n", " oneQdesigns.append(pygsti.protocols.MirrorRBDesign(pspec, depths[1], 10, qubit_labels=[q,], \n", " clifford_compilations=compilations,\n", " sampler='edgegrab', samplerargs=[0.],\n", " add_default_protocol=True))\n", " \n", "sim1Qdesign = pygsti.protocols.SimultaneousExperimentDesign(oneQdesigns)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we want to run this simultanoeus 1-qubit RB experiment alongside the 1-4 qubit RB experiments, we add it to the `designs` dictionary where we're storing all the experiment designs that are to be run together (but not in parallel)." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "designs['1Q-SRB'] = sim1Qdesign" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then we just combine them together in a `CombinedExperimentDesign`. This is then written to a directory in the same way as with all experiment designs. The dataset template contains all the circuits that need to be run. This will include all the circuits from all the sub-designs, including the simultaneous 1-qubit circuits in the necessary parallel form. After data is added to the template, it is then read-in in the same way as always." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "qubit_error_rate = 0.002\n", "def simulate_taking_data(data_template_filename):\n", " \"\"\"Simulate taking data and filling the results into a template dataset.txt file\"\"\"\n", " error_rates = {}\n", " for gn in pspec.gate_names:\n", " n = pspec.gate_num_qubits(gn)\n", " gate_error_rate = n * qubit_error_rate\n", " error_rates[gn] = [gate_error_rate/(4**n - 1)] * (4**n - 1)\n", " noisemodel = pygsti.models.create_crosstalk_free_model(pspec, stochastic_error_probs=error_rates)\n", " pygsti.io.fill_in_empty_dataset_with_fake_data(noisemodel, data_template_filename, num_samples=1000, seed=1234)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "combdesign = pygsti.protocols.CombinedExperimentDesign(designs)\n", "\n", "pygsti.io.write_empty_protocol_data(combdesign, '../tutorial_files/test_combrb_dir', clobber_ok=True)\n", "\n", "# -- fill in the dataset file in tutorial_files/test_rb_dir/data/dataset.txt --\n", "simulate_taking_data('../tutorial_files/test_combrb_dir/data/dataset.txt') # REPLACE with actual data-taking\n", "\n", "data = pygsti.io.load_data_from_dir('../tutorial_files/test_combrb_dir')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can then run any protocols that we want to on the imported data. Because we set `add_default_protocol=True` when creating the protocols, the imported data contains the `RB` protocols ready to run (with the appropriate optional arguments set for Mirror RB). We can run all these default protocols by creating a `pygsti.protocols.DefaultRunner()` protocol, and running it on the data.\n", "\n", "We can also run more protocols (e.g., a test for instability if the data is time-stamped) just by creating the relevant protocols objects, and passing them this data." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running protocol RB at ./1Q-RB\n", "Running protocol RB at ./2Q-RB\n", "Running protocol RB at ./3Q-RB\n", "Running protocol RB at ./4Q-RB\n", "Running protocol RB at ./1Q-SRB/('Q0',)\n", "Running protocol RB at ./1Q-SRB/('Q1',)\n", "Running protocol RB at ./1Q-SRB/('Q2',)\n", "Running protocol RB at ./1Q-SRB/('Q3',)\n" ] } ], "source": [ "protocol = pygsti.protocols.DefaultRunner()\n", "results = protocol.run(data)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "dict_keys([('Q0',), ('Q1',), ('Q2',), ('Q3',)])" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results['1Q-SRB'].keys()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `results` behaves like a dictionary, for accessing the individual results." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The RB error rate on 1Q-RB qubit is 0.007416058975985351\n", "The RB error rate on 2Q-RB qubit is 0.01469694357489764\n", "The RB error rate on 3Q-RB qubit is 0.0223674522807891\n", "The RB error rate on 4Q-RB qubit is 0.030603327965670758\n", "\n", "When running simultaneously, the RB error rate on ('Q0',) qubit is 0.007391539841511335\n", "When running simultaneously, the RB error rate on ('Q1',) qubit is 0.007500220175417738\n", "When running simultaneously, the RB error rate on ('Q2',) qubit is 0.007318437467928263\n", "When running simultaneously, the RB error rate on ('Q3',) qubit is 0.007671444306106501\n" ] } ], "source": [ "for i in ['1Q-RB', '2Q-RB', '3Q-RB' , '4Q-RB']:\n", " r = results[i].for_protocol['RB'].fits['A-fixed'].estimates['r']\n", " print('The RB error rate on {} qubit is {}'.format(i, r))\n", " \n", "print()\n", "for i in [('Q0',),('Q1',),('Q2',),('Q3',)]:\n", " r = results['1Q-SRB'][i].for_protocol['RB'].fits['A-fixed'].estimates['r']\n", " print('When running simultaneously, the RB error rate on {} qubit is {}'.format(i, r))" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "
Loading...
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "
\n", "
\n", "
\n", "\n", "
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "
\n", "
\n", "
\n", "\n", "
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "
\n", "
\n", "
\n", "\n", "
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\n", "
\n", "
\n", "
\n", "\n", "
\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "ws = pygsti.report.Workspace()\n", "ws.init_notebook_mode(autodisplay=True)\n", "for i in ['1Q-RB', '2Q-RB', '3Q-RB' , '4Q-RB']:\n", " ws.RandomizedBenchmarkingPlot(results[i].for_protocol['RB'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**For more information** and examples on running multiple benchmarking protocols on a processor, check out the [volumetric benchmarking tutorial](VolumetricBenchmarks.ipynb)." ] } ], "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.4" } }, "nbformat": 4, "nbformat_minor": 1 }