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.
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.
These 3 child classes translate Qubiter "English files" to "target" quantum languages IBM qasm, Google Cirq and Rigetti PyQuil,
respectively. These target quantum languages were chosen because they are very popular and their companies currently offer quantum computing devices on the cloud.
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.
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, 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.
# Make the qubiter directory the cwd (current working directory) and
# add its path to the path environment variable
import os
import sys
print(os.getcwd())
os.chdir('../../')
print(os.getcwd())
sys.path.insert(0,os.getcwd())
/home/rrtucci/PycharmProjects/qubiter/qubiter/jupyter_notebooks /home/rrtucci/PycharmProjects/qubiter
Next we import the class Qubiter_to_AnyQasm
and print its very informative docstring so you can read it:
from qubiter.device_specific.Qubiter_to_AnyQasm import *
from IPython.display import HTML, display
def disp(f):
dis_obj = HTML(SEO_writer.get_html_for_eng_or_pic_file(f))
display(dis_obj)
loaded OneQubitGate, WITHOUT autograd.numpy
# this tells notebook to send pager output to cell below instead of pager
def page_printer(data, start=0, screen_lines=0, pager_cmd=None):
if isinstance(data, dict):
data = data['text/plain']
print(data)
import IPython.core.page
IPython.core.page.page = page_printer
Qubiter_to_AnyQasm?
Init signature: Qubiter_to_AnyQasm( file_prefix, num_qbits, aqasm_name='', strict_mode=False, c_to_tars=None, write_qubiter_files=False, vars_manager=None, aqasm_ftype='txt', prelude_str=None, ending_str=None, **kwargs, ) Docstring: This abstract class is a child of SEO_reader. It reads an input English file and writes an AnyQasm file that is a translation of the input English file into the AnyQasm language. If the flag write_qubiter_files is set to True, this class will also write new English and Picture files that are in 1-1 onto line correspondence with the output AnyQasm file. Footnote: Some AnyQasm's distinguish between quantum registers qreg and classical registers creg. Qubiter does not use cregs because it uses the classical memory of your Linux PC instead. AnyQasm has an intricate set of commands for measurements. Qubiter has a complete set of measurement commands too (see MEAS in Rosetta stone). The AnyQasm and Qubiter measurement commands can obviously be translated into each other. We leave that part of the translation to a future version of this class. This class can run in either a strict or a non-strict mode depending on the flag `strict_mode`, which equals False in default mode. In the strict mode, the set of gates allowed is constrained to a small but universal set that is specified below, and that is allowed in any target qasm. In the non-strict mode, more gates are allowed that depend on specific target qasm. In the strict mode, the program will end if you try to use gates that are not allowed. In the non-strict mode, the program will end if you try to use gates for a target language that have not been implemented yet in the Qubiter class targeting that language, often because the target language doesn't support those gates. Will refer to target qasm as AnyQasm or aqasm Next we give a description of the strict_mode: In the strict mode, the input English file that is read can only have lines of the following types or else the program will abort with an error message: 1. single qubit rotations (HAD2, SIGX, SIGY, SIGZ, ROTX, ROTY, ROTZ or ROTN with no controls) 2. simple CNOTs (SIGX with a single True control). Call them c->t=( c, t) if c is the control and t the target. (c, t) must be allowed by 'c_to_tars'. 3. NOTA or PRINT lines. PRINT lines are commented out. If you have an English file that contains lines that are more complicated than this (because, for example, they contain rotations with one or more controls attached, or because a CNOT is not allowed according to 'c_to_tars'), you can use the expander classes CGateExpander, DiagUnitaryExpander, MultiplexorExpander, and ForbiddenCNotExpander to expand the circuit to an equivalent albeit longer circuit that satisfies constraints 1, 2, 3. This class can handle a chip with any number of qubits. This class halts execution if it encounters a CNOT that is disallowed according to the input 'c_to_tars'. 'c_to_tars' varies with chip. Some 'c_to_tars's are listed in the files 'chip_couplings_...' found in same folder as this file. If c_to_tars = None, the class assumes any CNOT is possible. Attributes ---------- all_fun_names : list[str] a list of all the distinct function names encountered in circuit all_var_nums : list[int] a list of all distinct numbers of the variables encountered in circuit aqasm_name : str the name of the aqasm language, for example, IBMqasm. Used as ending of file name, between '_' and '.txt' aqasm_path : str path to aqasm file aqasm_out : _io.TextIOWrapper This output stream is used to write an aqasm file based on the input English file. c_to_tars : dict[int, list[int]] a dictionary mapping j in range(num_qbits) to a list, possibly empty, of the physically allowed targets of qubit j, when j is the control of a CNOT. If c_to_tars = None, the class assumes any CNOT is possible. file_prefix : str num_qbits : int qbtr_wr : SEO_writer A SEO_writer object created iff write_qubiter_files is True. strict_mode : bool vprefix : str all variables in aqasm file will be called vprefix + an int write_qubiter_files : bool The class always writes an AnyQasm text file based on the input English file that is read. Iff this is True, the class also writes English and Picture files in 1-1 line correspondence with the output AnyQasm file Init docstring: Constructor Parameters ---------- file_prefix : str num_qbits : int aqasm_name : str strict_mode : bool c_to_tars : dict[int, list[int]]|None write_qubiter_files : bool vars_manager : PlaceholderManager aqasm_ftype : str file type of output aqasm file. If this equals 'txt', name of aqasm file will end in '.txt' prelude_str : str | None string to write as prelude to aqasm file. If None, then the override method of self.write_prelude() is called ending_str : str | None string to write as ending to aqasm file. If None, then the override method of self.write_ending() is called Returns ------- File: ~/PycharmProjects/qubiter/qubiter/device_specific/Qubiter_to_AnyQasm.py Type: type Subclasses:
import qubiter.utilities_gen as utg
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.
from qubiter.device_specific.Qubiter_to_IBMqasm import *
import qubiter.device_specific.chip_couplings_ibm as ibm
file_prefix = 'qbtr2ibm_test'
aqasm_name = 'IBMqasm'
num_qbits = 5
c_to_tars = ibm.ibmq5YorktownTenerife_c_to_tars
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.
Note that this file contains no placeholder variables as IBM Terra currently does not support them
fpath = file_prefix + '_5_eng.txt'
with open(utg.preface(fpath)) as f:
disp(f)
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 45.0 AT 2 | 15 | P1PH 45.0 AT 2 IF 0T | 16 | SWAP 2 0 |
Next we create an object of the translator class.
Qubiter_to_IBMqasm(file_prefix, num_qbits, aqasm_name=aqasm_name,
c_to_tars=c_to_tars, write_qubiter_files=True)
<qubiter.device_specific.Qubiter_to_IBMqasm.Qubiter_to_IBMqasm at 0x7fe0b05b6250>
The following 3 files were generated by the constructor just called:
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).
File 3 is the IBM qasm file that we wanted.
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.
from qubiter.device_specific.Qubiter_to_GoogleCirq import *
file_prefix = "qbtr2google_test"
aqasm_name = 'GooCirq'
num_qbits = 5
c_to_tars = 'do_fill' # filled by constructor
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.
Note that this file contains several placeholder variables as the latest versions of Qubiter and Cirq support them
fpath = file_prefix + '_5_eng.txt'
with open(utg.preface(fpath)) as f:
disp(f)
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 #1 AT 2 | 17 | P1PH -#1 AT 2 IF 0T | 18 | SWAP 2 0 |
Next we create an object of the translator class.
Qubiter_to_GoogleCirq(file_prefix, num_qbits, aqasm_name=aqasm_name,
c_to_tars=c_to_tars, write_qubiter_files=True)
<qubiter.device_specific.Qubiter_to_GoogleCirq.Qubiter_to_GoogleCirq at 0x7fe0d8483790>
The following 3 files were generated by the constructor just called:
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).
File 3 is the Google Cirq file that we wanted.
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.
from qubiter.device_specific.Qubiter_to_RigettiPyQuil import *
import qubiter.device_specific.chip_couplings_rigetti as rig
file_prefix = "qbtr2rigetti_test"
aqasm_name = 'RigPyQuil'
num_qbits = 6
c_to_tars = rig.rigetti20_c_to_tars
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.
Note that this file contains several placeholder variables as the latest versions of Qubiter and PyQuil support them
fpath = file_prefix + '_6_eng.txt'
with open(utg.preface(fpath), "r") as f:
disp(f)
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 -#1 AT 2 | 15 | P0PH #1 AT 2 IF 0F | 16 | P0PH -#1 AT 2 IF 0T | 17 | P1PH 45.0 AT 2 IF 0F | 18 | P1PH 45.0 AT 2 IF 0T | 19 | SWAP 2 0 |
Next we create an object of the translator class.
Qubiter_to_RigettiPyQuil(file_prefix, num_qbits, aqasm_name=aqasm_name,
c_to_tars=c_to_tars, write_qubiter_files=True)
<qubiter.device_specific.Qubiter_to_RigettiPyQuil.Qubiter_to_RigettiPyQuil at 0x7fe0b05ba710>
The following 3 files were generated by the constructor just called:
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).
File 3 is the Rigetti PyQuil file that we wanted.