{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n# External Interfaces: Introduction\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example, we demonstrate how to convert between the |True-Q| python circuit\nrepresentation and other popular third party representations. These conversions\nwill only be available if the corresponding python packages are installed.\n\nWe start by defining a test circuit to work with:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import trueq as tq\n\ncircuit = tq.Circuit(\n [\n {(0,): tq.Gate.x, (1,): tq.Gate.y},\n {(0, 2): tq.Gate.cz, (1,): tq.Gate.x},\n {(3,): tq.Gate.h, (5,): tq.Gate.s},\n ]\n)\ncircuit.measure_all()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cirq\nConvert the circuit to a Cirq circuit object:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "cirq_circuit = circuit.to_cirq()\ncirq_circuit" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Perform the inverse conversion (to_trueq() is monkey-patched onto their circuit object\nat |True-Q| import time):\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "cirq_circuit.to_trueq()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## PyQuil\nConvert the circuit to a PyQuil circuit object:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pyquil_circuit = circuit.to_pyquil()\nprint(pyquil_circuit)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Perform the inverse conversion (to_trueq() is monkey-patched onto their circuit object\nat |True-Q| import time):\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "pyquil_circuit.to_trueq()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Qiskit\nSet the preferred gates to build into (See below for more details), then convert the\ncircuit to a Qiskit circuit object:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "tq.interface.qiskit.set_config([\"CXGate\", \"UGate\"])\nqiskit_circuit = circuit.to_qiskit()\nqiskit_circuit.draw(\"mpl\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Perform the inverse conversion (to_trueq() is monkey-patched onto their circuit object\nat |True-Q| import time):\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "qiskit_circuit.to_trueq()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interface Config\nDuring conversion between representations in |True-Q| and other software packages,\nthere is often a degeneracy in how a gate may be converted. For example, an identity\ngate could be written as ``Z(phi)``, ``X(phi)``, ``Y(phi)``, ... with ``phi = 0``.\n\nIn these cases, this degeneracy can be broken by setting the preferred order of gate\nconversion. This is done in the interfaces through a :py:class:`~trueq.Config` which\ncontains a collection of :py:class:`~trueq.config.GateFactory`\\s. Each of these\nfactories has the exact name and parameters of the corresponding gate representation\nin the external software. During the conversion of any specific gate from |True-Q|\ninto the external software, each of these factories is used in order until the\nconversion is possible.\n\nThe default settings for all interfaces is to have the defined config contain all\npossible gates allowed in the external software, even though there are typically\ndegeneracies. This default configuration is available through the\n:py:meth:`~trueq.interface.base.Interface.default_config` method on every interface.\n\nThe current active config may be changed through the respective\n:py:meth:`~trueq.interface.base.Interface.set_config` and\n:py:meth:`~trueq.interface.base.Interface.get_config` which are also available on\nevery interface.\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Look at the config list for the interface between |True-Q| and Cirq:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "std_config = tq.interface.cirq.default_config()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Set a reduced config, containing only ``CNOT``, ``XPowGate``, and ``ZPowGate``:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "tq.interface.cirq.set_config([\"CNOT\", \"XPowGate\", \"ZPowGate\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This may have also been set through a subset of the default config:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "tq.interface.cirq.set_config(std_config.subset(names=[\"CNOT\", \"XPowGate\", \"ZPowGate\"]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Convert the circuit defined above to Cirq using the updated config:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "circuit.to_cirq()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. note ::\n Setting the config to ``None`` resets to the default config.\n\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Reset the config to the default:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "tq.interface.cirq.set_config(None)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Convert the circuit to Cirq using the default config\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "circuit.to_cirq()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As you can see in the printed circuits, changing the config alters the gates used in\nconverting from |True-Q| to other software. For example, removing the ``X`` gate from\nthe config causes the interface to pick the next viable representation of this\noperation, so that the ``X`` gates are given as rotations about ``X`` by $\\pi$.\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 }