{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Translating Qubiter English file to AnyQasm file\n", "\n", "aqasm= a quantum assembly language, a low level quantum language, containing a small but universal set of quantum gates such as CNOTs and single qubit rotations.\n", "\n", "Note that in the `device_specific` folder, Qubiter contains an abstract class called `Qubiter_to_AnyQasm`. This abstract class is the parent to 3 other classes in the same folder called `Qubiter_to_IBMqasm`, `Qubiter_to_GoogleCirq` and `Qubiter_to_RigettiPyQuil`. In this notebook, we will give examples of usage of these 3 child classes.\n", "These 3 child classes translate Qubiter \"English files\" to \"target\" quantum languages IBM qasm, Google Cirq and Rigetti PyQuil,\n", "respectively. These target quantum languages were chosen because they are very popular and their companies currently offer quantum computing devices on the cloud. \n", "The parent class `Qubiter_to_AnyQasm` does most of the hard work, so it will be easy in future to add child classes to Qubiter for other target quantum languages.\n", "\n", "\n", "For all 3 target quantum languages, you can write a Jupyter notebook that translates a Qubiter English file into a bridge file in the target quantum language, \n", "and then automatically transmits that bridge file to the target company's cloud service, and gets a response back from that cloud service. That way you can run a q circuit on the target company's hardware directly from a Jupyter notebook on your computer." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/home/rrtucci/PycharmProjects/qubiter/qubiter/jupyter_notebooks\n", "/home/rrtucci/PycharmProjects/qubiter\n" ] } ], "source": [ "# Make the qubiter directory the cwd (current working directory) and \n", "# add its path to the path environment variable\n", "import os\n", "import sys\n", "print(os.getcwd())\n", "os.chdir('../../')\n", "print(os.getcwd())\n", "sys.path.insert(0,os.getcwd())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next we import the class `Qubiter_to_AnyQasm` and print its very informative docstring so you can read it:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "loaded OneQubitGate, WITHOUT autograd.numpy\n" ] } ], "source": [ "from qubiter.device_specific.Qubiter_to_AnyQasm import *\n", "from IPython.display import HTML, display\n", "def disp(f):\n", " dis_obj = HTML(SEO_writer.get_html_for_eng_or_pic_file(f))\n", " display(dis_obj)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# this tells notebook to send pager output to cell below instead of pager\n", "\n", "def page_printer(data, start=0, screen_lines=0, pager_cmd=None):\n", " if isinstance(data, dict):\n", " data = data['text/plain']\n", " print(data)\n", "\n", "import IPython.core.page\n", "IPython.core.page.page = page_printer" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[0;31mInit signature:\u001b[0m\n", "\u001b[0mQubiter_to_AnyQasm\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mfile_prefix\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mnum_qbits\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0maqasm_name\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mstrict_mode\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mc_to_tars\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mwrite_qubiter_files\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mvars_manager\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0maqasm_ftype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'txt'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mprelude_str\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mending_str\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mDocstring:\u001b[0m \n", "This abstract class is a child of SEO_reader. It reads an input English\n", "file and writes an AnyQasm file that is a translation of the input\n", "English file into the AnyQasm language. If the flag write_qubiter_files\n", "is set to True, this class will also write new English and Picture files\n", "that are in 1-1 onto line correspondence with the output AnyQasm file.\n", "\n", "Footnote: Some AnyQasm's distinguish between quantum registers qreg and\n", "classical registers creg. Qubiter does not use cregs because it uses the\n", "classical memory of your Linux PC instead. AnyQasm has an intricate set\n", "of commands for measurements. Qubiter has a complete set of measurement\n", "commands too (see MEAS in Rosetta stone). The AnyQasm and Qubiter\n", "measurement commands can obviously be translated into each other. We\n", "leave that part of the translation to a future version of this class.\n", "\n", "This class can run in either a strict or a non-strict mode depending on\n", "the flag `strict_mode`, which equals False in default mode. In the\n", "strict mode, the set of gates allowed is constrained to a small but\n", "universal set that is specified below, and that is allowed in any target\n", "qasm. In the non-strict mode, more gates are allowed that depend on\n", "specific target qasm. In the strict mode, the program will end if you\n", "try to use gates that are not allowed. In the non-strict mode,\n", "the program will end if you try to use gates for a target language that\n", "have not been implemented yet in the Qubiter class targeting that\n", "language, often because the target language doesn't support those gates.\n", "\n", "Will refer to target qasm as AnyQasm or aqasm\n", "\n", "Next we give a description of the strict_mode:\n", "\n", "In the strict mode, the input English file that is read can only have\n", "lines of the following types or else the program will abort with an\n", "error message:\n", "\n", "1. single qubit rotations (HAD2, SIGX, SIGY, SIGZ, ROTX, ROTY,\n", "ROTZ or ROTN with no controls)\n", "\n", "2. simple CNOTs (SIGX with a single True control). Call them c->t=(\n", "c, t) if c is the control and t the target. (c, t) must be allowed\n", "by 'c_to_tars'.\n", "\n", "3. NOTA or PRINT lines. PRINT lines are commented out.\n", "\n", "If you have an English file that contains lines that are more\n", "complicated than this (because, for example, they contain rotations with\n", "one or more controls attached, or because a CNOT is not allowed\n", "according to 'c_to_tars'), you can use the expander classes\n", "CGateExpander, DiagUnitaryExpander, MultiplexorExpander,\n", "and ForbiddenCNotExpander to expand the circuit to an equivalent albeit\n", "longer circuit that satisfies constraints 1, 2, 3.\n", "\n", "This class can handle a chip with any number of qubits.\n", "\n", "This class halts execution if it encounters a CNOT that is disallowed\n", "according to the input 'c_to_tars'. 'c_to_tars' varies with chip. Some\n", "'c_to_tars's are listed in the files 'chip_couplings_...' found in same\n", "folder as this file. If c_to_tars = None, the class assumes any CNOT is\n", "possible.\n", "\n", "\n", "Attributes\n", "----------\n", "all_fun_names : list[str]\n", " a list of all the distinct function names encountered in circuit\n", "all_var_nums : list[int]\n", " a list of all distinct numbers of the variables encountered in circuit\n", "aqasm_name : str\n", " the name of the aqasm language, for example, IBMqasm. Used as ending\n", " of file name, between '_' and '.txt'\n", "aqasm_path : str\n", " path to aqasm file\n", "aqasm_out : _io.TextIOWrapper\n", " This output stream is used to write an aqasm file based on the input\n", " English file.\n", "c_to_tars : dict[int, list[int]]\n", " a dictionary mapping j in range(num_qbits) to a list, possibly empty,\n", " of the physically allowed targets of qubit j, when j is the control\n", " of a CNOT. If c_to_tars = None, the class assumes any CNOT is\n", " possible.\n", "file_prefix : str\n", "num_qbits : int\n", "qbtr_wr : SEO_writer\n", " A SEO_writer object created iff write_qubiter_files is True.\n", "strict_mode : bool\n", "vprefix : str\n", " all variables in aqasm file will be called vprefix + an int\n", "write_qubiter_files : bool\n", " The class always writes an AnyQasm text file based on the input\n", " English file that is read. Iff this is True, the class also writes\n", " English and Picture files in 1-1 line correspondence with the output\n", " AnyQasm file\n", "\u001b[0;31mInit docstring:\u001b[0m\n", "Constructor\n", "\n", "Parameters\n", "----------\n", "file_prefix : str\n", "num_qbits : int\n", "aqasm_name : str\n", "strict_mode : bool\n", "c_to_tars : dict[int, list[int]]|None\n", "write_qubiter_files : bool\n", "vars_manager : PlaceholderManager\n", "aqasm_ftype : str\n", " file type of output aqasm file. If this equals 'txt', name of\n", " aqasm file will end in '.txt'\n", "prelude_str : str | None\n", " string to write as prelude to aqasm file. If None, then the\n", " override method of self.write_prelude() is called\n", "ending_str : str | None\n", " string to write as ending to aqasm file. If None, then the\n", " override method of self.write_ending() is called\n", "\n", "Returns\n", "-------\n", "\u001b[0;31mFile:\u001b[0m ~/PycharmProjects/qubiter/qubiter/device_specific/Qubiter_to_AnyQasm.py\n", "\u001b[0;31mType:\u001b[0m type\n", "\u001b[0;31mSubclasses:\u001b[0m \n", "\n" ] } ], "source": [ "Qubiter_to_AnyQasm?" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import qubiter.utilities_gen as utg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Translating to IBMqasm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the following example, we will assume that we are dealing with a specific ibmq chip which contains 5 qubits. The target language will be IBM qasm/Terra." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "from qubiter.device_specific.Qubiter_to_IBMqasm import *\n", "import qubiter.device_specific.chip_couplings_ibm as ibm\n", "file_prefix = 'qbtr2ibm_test'\n", "aqasm_name = 'IBMqasm'\n", "num_qbits = 5\n", "c_to_tars = ibm.ibmq5YorktownTenerife_c_to_tars" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We've pre-inserted in Qubiter's io_folder an English file that puts the Qubiter translator through its paces. Let's print that file. \n", "\n", "> Note that this file contains no placeholder variables as IBM Terra currently does not support them" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
1
HAD2  AT  3
2
SIGX  AT  2
3
SIGY  AT  2
4
SIGZ  AT  2
5
ROTX  30.0  AT  3
6
ROTY  25.0  AT  3
7
ROTZ  60.0  AT  3
8
ROTN  30.0  45.0  60.0  AT 4
9
NOTA  0->1 allowed by c_to_tars
10
SIGX  AT  1  IF  0T
11
NOTA  1->0 not allowed by c_to_tars
12
NOTA SIGX  AT  0  IF  1T
13
NOTA    not allowed in strict mode
14
P1PH\t45.0\tAT\t2
15
P1PH\t45.0\tAT\t2\tIF\t0T
16
SWAP\t2\t0
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fpath = file_prefix + '_5_eng.txt'\n", "with open(utg.preface(fpath)) as f:\n", " disp(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next we create an object of the translator class." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Qubiter_to_IBMqasm(file_prefix, num_qbits, aqasm_name=aqasm_name,\n", " c_to_tars=c_to_tars, write_qubiter_files=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following 3 files were generated by the constructor just called:\n", "\n", "1. ../io_folder/qbtr2ibm_test_X1_5_eng.txt\n", "2. ../io_folder/qbtr2ibm_test_X1_5_ZLpic.txt\n", "3. ../io_folder/qbtr2ibm_test_IBMqasm.txt\n", "\n", "Files 1 and 2 are Qubiter style English and Picture files (they differ from the input English file principally in that they include more NOTA lines).\n", "\n", "File 3 is the IBM qasm file that we wanted. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Translating to Google Cirq" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the following example, we will assume that we are dealing with Google's Bristlecone chip. This chip contains 72 qubits, but we will only use the first 5. The target language will be Google's Cirq." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "from qubiter.device_specific.Qubiter_to_GoogleCirq import *\n", "file_prefix = \"qbtr2google_test\"\n", "aqasm_name = 'GooCirq'\n", "num_qbits = 5\n", "c_to_tars = 'do_fill' # filled by constructor" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We've pre-inserted in Qubiter's io_folder an English file that puts the Qubiter translator through its paces. Let's print that file.\n", "\n", "> Note that this file contains several placeholder variables as the latest versions of Qubiter and Cirq support them\n" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
1
HAD2  AT  3
2
SIGX  AT  2
3
SIGY  AT  2
4
SIGZ  AT  2
5
ROTX  #1*.5  AT  3
6
ROTY  -#1  AT  3
7
ROTZ  60.0  AT  3
8
ROTN  30.0  45.0  60.0  AT 4
9
NOTA  1->0 allowed by c_to_tars
10
SIGX  AT  0  IF  1T
11
NOTA  0->1 allowed by c_to_tars
12
SIGX  AT  1  IF  0T
13
NOTA  1->2 not allowed by c_to_tars
14
NOTA  SIGX  AT  2  IF  1T
15
NOTA  not allowed in strict mode
16
P1PH\t#1\tAT\t2
17
P1PH\t-#1\tAT\t2\tIF\t0T
18
SWAP\t2\t0
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fpath = file_prefix + '_5_eng.txt'\n", "with open(utg.preface(fpath)) as f:\n", " disp(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next we create an object of the translator class." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Qubiter_to_GoogleCirq(file_prefix, num_qbits, aqasm_name=aqasm_name,\n", " c_to_tars=c_to_tars, write_qubiter_files=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following 3 files were generated by the constructor just called:\n", "\n", "1. ../io_folder/qbtr2google_test_X1_5_eng.txt\n", "2. ../io_folder/qbtr2google_test_X1_5_ZLpic.txt\n", "3. ../io_folder/qbtr2google_test_GooCirq.txt\n", "\n", "Files 1 and 2 are Qubiter style English and Picture files (they differ from the input English file\n", "principally in that they include more NOTA lines).\n", "\n", "File 3 is the Google Cirq file that we wanted." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Translating to Rigetti PyQuil" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the following example, we will assume that we are dealing with Rigetti's Acorn chip. This chip contains 20 qubits (one of them, number 3, is inactive), but we will only use the first 6. The target language will be Rigetti's PyQuil." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "from qubiter.device_specific.Qubiter_to_RigettiPyQuil import *\n", "import qubiter.device_specific.chip_couplings_rigetti as rig\n", "file_prefix = \"qbtr2rigetti_test\"\n", "aqasm_name = 'RigPyQuil'\n", "num_qbits = 6\n", "c_to_tars = rig.rigetti20_c_to_tars" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We've pre-inserted in Qubiter's io_folder an English file that puts the Qubiter translator through its paces. Let's print that file.\n", "\n", "> Note that this file contains several placeholder variables as the latest versions of Qubiter and PyQuil support them" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
1
HAD2  AT  3
2
SIGX  AT  2
3
SIGY  AT  2
4
SIGZ  AT  2
5
ROTX  #1*.5  AT  3
6
ROTY  -#1  AT  3
7
ROTZ  60.0  AT  3
8
ROTN  30.0  45.0  60.0  AT 4
9
NOTA  0->5 allowed by c_to_tars
10
SIGX  AT  5  IF  0T
11
NOTA  0->1 not allowed by c_to_tars
12
NOTA SIGX  AT  1  IF  0T
13
NOTA    not allowed in strict mode
14
P1PH\t-#1\tAT\t2
15
P0PH\t#1\tAT\t2\tIF\t0F
16
P0PH\t-#1\tAT\t2\tIF\t0T
17
P1PH\t45.0\tAT\t2\tIF\t0F
18
P1PH\t45.0\tAT\t2\tIF\t0T
19
SWAP\t2\t0
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fpath = file_prefix + '_6_eng.txt'\n", "with open(utg.preface(fpath), \"r\") as f:\n", " disp(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next we create an object of the translator class." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Qubiter_to_RigettiPyQuil(file_prefix, num_qbits, aqasm_name=aqasm_name,\n", " c_to_tars=c_to_tars, write_qubiter_files=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following 3 files were generated by the constructor just called:\n", "\n", "1. ../io_folder/qbtr2rigetti_test_X1_6_eng.txt\n", "2. ../io_folder/qbtr2rigetti_test_X1_6_ZLpic.txt\n", "3. ../io_folder/qbtr2rigetti_test_RigPyQuil.txt\n", "\n", "Files 1 and 2 are Qubiter style English and Picture files (they differ from the input English file principally in that they include more NOTA lines).\n", "\n", "File 3 is the Rigetti PyQuil file that we wanted." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.10.9" }, "toc": { "base_numbering": 1, "colors": { "hover_highlight": "#DAA520", "running_highlight": "#FF0000", "selected_highlight": "#FFD700" }, "moveMenuLeft": true, "nav_menu": { "height": "51px", "width": "252px" }, "navigate_menu": true, "number_sections": true, "sideBar": true, "skip_h1_title": false, "threshold": 4, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": "block", "toc_window_display": false, "widenNotebook": false } }, "nbformat": 4, "nbformat_minor": 4 }