{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Readout Calibration (RCAL)\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example illustrates how to generate readout calibration (:tqdoc:`RCAL`\\) circuits\nand use them to correct readout errors in other circuits. While this example uses a\n:doc:`simulator<../../guides/run/simulator>` to execute the circuits, the same\nprocedure can be followed for hardware applications.\n\nThe code below generates RCAL circuits for qubits ``0`` and ``1``, populates their\nresults using a simulator with readout error, and displays their confusion matrices.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import trueq as tq\n\n# generate RCAL circuits to measure the readout errors on qubits [0, 1]\ncircuits = tq.make_rcal([0, 1])\n\n# initialize a simulator with a 20% readout error on every qubit\nsim = tq.Simulator().add_readout_error(0.2)\n\n# run the circuits on the simulator to populate their results\nsim.run(circuits, n_shots=1000)\n\n# display the confusion matrices\ncircuits.fit()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Automatic Correction\n\nIf your circuit collection contains RCAL circuits, then that information will be\nused automatically to apply readout correction to your circuits when you call\n:py:meth:`~trueq.CircuitCollection.fit` or :py:meth:`~trueq.CircuitCollection.plot`\\.\nThe code below illustrates this for :tqdoc:`SRB` circuits executed on a noisy\nsimulator with readout error. It also shows how you can view the results with and\nwithout readout correction being applied.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# generate RCAL circuits to measure the readout errors on qubits [0, 1, 2]\ncircuits = tq.make_rcal([0, 1, 2])\n\n# generate SRB circuits to simultaneously characterize a single qubit [0] and\n# a pair of qubits [1, 2] with 30 circuits for each random cycle in [4, 32, 64]\ncircuits.append(tq.make_srb([[0], [1, 2]], [4, 32, 64], 30))\n\n# initialize a noisy simulator with a large 10% readout error\nsim = tq.Simulator().add_stochastic_pauli(px=0.01).add_readout_error(0.1)\n\n# RCAL generally needs more shots than the other protocols because it is estimating\n# an absolute value rather than a decay over randomizations, thus in this simulation\n# we use different amounts of shots for SRB and RCAL to populate their results\nsim.run(circuits.subset(protocol=[\"RCAL\"]), n_shots=50)\nsim.run(circuits.subset(protocol=\"RCAL\"), n_shots=1000)\n\n# plot the exponential decay with readout correction,\n# where each expectation value (dot) has been compensated\ncircuits.plot.raw()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To avoid performing readout correction during analysis, we can remove all RCAL\ncircuits from the collection before calling :py:meth:`~trueq.CircuitCollection.plot`\\.\nNotice that the y-intercept is lower than in the plot above.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# plot the exponential decay without readout correction\ncircuits.subset(protocol=\"SRB\").plot.raw()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Optional Arguments\n\nOne optional argument to :py:func:`~trueq.make_rcal` is ``independent=True`` that\nspecifies whether it can be assumed that the readout error is independent over qubits.\nUnder this assumption, only two circuits are required, whereas $2^n$ circuits\nare required when this assumption does not hold. Note that if you measure the readout\ncalibration matrix in both independent and non-independent modes, any observed\nnon-independence could potentially be due to gate crosstalk errors.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# generate RCAL circuits assuming that readout error is qubit-dependent\ncircuits = tq.make_rcal([0, 1, 2], independent=False)\n\n# print the length of the circuits\nlen(circuits)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can see, the above circuit collection contains eight circuits, whereas it would\nnormally contain only two if ``independent`` was set to ``True``.\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another optional argument to :py:func:`~trueq.make_rcal` is ``stagger=False`` that\nspecifies whether $X$ gates should appear in separate uniquely marked cycles. If\nthe gates are much worse when applied in parallel, then staggering them will reduce\nsystematic errors, provided that the gate duration multiplied by the number of qubits\nis much shorter than $T_1$.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# generate RCAL circuits with staggered X gates\ncircuits = tq.make_rcal([0, 1, 2], stagger=True)\n\n# display the first circuit\ncircuits[0]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# display the second circuit\ncircuits[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The circuit above contains four cycles with the $X$ gates appearing in separate\nmarked cycles, which would normally occupy a single cycle if ``stagger`` was set to\n``False``.\n\n" ] } ], "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.6.8" } }, "nbformat": 4, "nbformat_minor": 0 }