{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Running Jobs on Qiskit Backends\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import trueq as tq\nimport qiskit as qk" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Running jobs on a Qiskit backend requires credentials for the provider of the backend.\nSee the provider's documentation for instructions for how to set this up. For example,\nthe following snippet demonstrates how one instantiates a remote backend object from\nthe IBM Quantum Experience. This example file does not have any credentials, so we\nmake do with the local qiskit simulator which uses the same backend abstraction.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "have_credentials = False\n\nif have_credentials:\n qk.IBMQ.load_account()\n provider = qk.IBMQ.get_provider()\n # request the 5-qubit chip called \"ibmqx2\"\n backend = provider.get_backend(\"ibmqx2\")\nelse:\n from qiskit.test.mock import FakeMelbourne\n\n backend = FakeMelbourne()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Submitting a Circuit Collection\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# Define a 3-qubit cycle to work with.\ncycle = {0: tq.Gate.x, 1: tq.Gate.y, 2: tq.Gate.h}\n\n# Generate a circuit collection to measure noise.\ncircuits = tq.make_knr(cycle, [4, 32, 64], 24)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The executor (defined below) will automatically attempt to batch the circuit\ncollection into the maximum number of circuits per job that the backend supports.\nHere, however, we manually batch beforehand. Supposing the backend accepts at most\n75 circuits and has a memory cutoff for the number of gates allowed per job, we\nchoose to riffle circuits in the batch by circuit depth. In our protocol above, we\nselected 3 sequence lengths, 4, 32, and 64, with 24 random circuits per sequence\nlength per configuration. Thus we use fit $24\\times 3+2=72$ circuits per batch,\nwhere the extra $2$ are readout calibration (:tqdoc:`RCAL`) circuits.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "ro_circuits = tq.make_rcal(circuits.labels)\nbatches = circuits.batch(74, extra_circuits=ro_circuits, sequencer=tq.sequencer.RIFFLER)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Run the batches on our backend. If a filename is provided, it will periodically save\nto the given file so that we can resume the experiment if, for example, our python\nkernel crashes.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "ex = tq.interface.Executor(batches, backend, n_shots=128)\n\n# the executor is asynchronous, call a blocking function to wait for it to finish\nex.results()\n\ncircuits.plot.timestamps()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. note ::\n\n When running in Jupyter, the executor has an automatically updating output which\n relies on IPywidgets being installed and enabled. If these are not installed then\n no display will show up when running the executor in Jupyter.\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Transpiling for a Specific Backend\nSometimes it is useful to see what the circuit conversion is doing for a particular\ncircuit. To do this, we first instantiate a True-Q configuration object from our\ndesired backend. This will contain the device topology and native gates of the\nbackend. We create a compiler object based on this configuration.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# .. note ::\n#\n# This process is done during submission automatically by the\n# :py:class:`~trueq.interface.Executor`\\, and the steps below should only be used as\n# a reference. The output of this should not be put into the ``Executor`` or it will\n# apply the same compiler operations a second time, which may alter the circuit\n# further.\n\nconfig = tq.interface.qiskit.config_from_backend(backend)\ntranspiler = tq.Compiler.from_config(config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define a circuit.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "circuit = tq.Circuit([{4: tq.Gate.random(2), 5: tq.Gate.x}])\ncircuit" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Transpile the circuit based on the device.\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "transpiled_circuit = transpiler.compile(circuit)\ntranspiled_circuit" ] } ], "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 }