from qubiter.Controls import *
from qubiter.SEO_reader import *
from qubiter.SEO_writer import *
from qubiter.UnitaryMat import *
import qubiter.utilities_gen as ut
[docs]class Qubiter_to_AnyQasm(SEO_reader):
"""
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
"""
[docs] def __init__(self, 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):
"""
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
-------
"""
self.file_prefix = file_prefix
self.num_qbits = num_qbits
vman = PlaceholderManager(eval_all_vars=False)
rdr = SEO_reader(file_prefix, num_qbits, vars_manager=vman,
write_log=True)
self.all_var_nums = rdr.vars_manager.all_var_nums
self.all_fun_names = rdr.vars_manager.all_fun_names
self.aqasm_name = aqasm_name
self.strict_mode = strict_mode
self.vprefix = 'rads'
self.c_to_tars = c_to_tars
self.write_qubiter_files = write_qubiter_files
self.aqasm_path = file_prefix +\
'_' + aqasm_name + '.' + aqasm_ftype
self.aqasm_out = open(utg.preface(self.aqasm_path), 'wt')
self.qbtr_wr = None
if write_qubiter_files:
emb = CktEmbedder(num_qbits, num_qbits)
out_file_prefix = SEO_reader.xed_file_prefix(file_prefix)
self.qbtr_wr = SEO_writer(out_file_prefix, emb)
if prelude_str is not None:
self.write(prelude_str)
else:
self.write_prelude()
vman1 = PlaceholderManager(eval_all_vars=False)
SEO_reader.__init__(self, file_prefix, num_qbits,
vars_manager=vman1, **kwargs)
if ending_str is not None:
self.write(ending_str)
else:
self.write_ending()
self.aqasm_out.close()
if write_qubiter_files:
self.qbtr_wr.close_files()
[docs] def write(self, s):
"""
Writes string s to aqasm and qubiter out files.
Parameters
----------
s : str
Returns
-------
None
"""
self.aqasm_out.write(s + '\n')
if self.write_qubiter_files:
lines = s.split('\n')
for line in lines:
self.qbtr_wr.write_NOTA(line)
[docs] def write_prelude(self):
"""
Abstract function, writes AnyQasm's opening statements before calls
to use_ methods for gates.
Returns
-------
None
"""
assert False
[docs] def write_ending(self):
"""
Abstract function, writes AnyQasm's ending statements after calls to
use_ methods for gates.
Returns
-------
None
"""
assert False
[docs] def new_var_name(self, var_name, coda='', strict=False):
"""
Starts by asserting that var_name is a legal variable name.
If var_name is not functional, this method replaces # in var_name by
self.vprefix and adds coda to end of string. For example,
if self.vprefix='rads' and var_name='-#2*.5", then output is
'-rads2*.5' + coda
If var_name is functional, this method replaces each # in var_name
by self.vprefix, adds commas and parenthesis, and adds coda to end
of string. For example, if self.vprefix='rads' and
var_name='-fun#1#2', then output is '-fun(rads1, rads2)' + coda
The above applies only if strict=False. In the strict mode, only an
empty coda is allowed for functional placeholders. For
non-functional placeholders, if var_name contains an *, then the str
after the * and the coda are merged using eval().
Parameters
----------
var_name : str
coda : str
strict : bool
Returns
-------
str
"""
assert PlaceholderManager.is_legal_var_name(var_name)
if not PlaceholderManager.is_functional_var(var_name):
new_coda = coda
if coda:
assert len(coda) > 1, "illegal coda: " + coda
star_pos = var_name.find("*")
if strict and star_pos != -1 and coda:
assert coda[0] == '*', "A coda must start with * " +\
"in strict mode. Got coda: " + coda
fac1 = var_name[star_pos+1:]
fac2 = coda[1:]
fac12 = fac1 + '*' + fac2
try:
new_coda = '*' + str(eval(fac12))
except:
assert False, 'cannot eval "' +\
fac12 + '" to merge "' +\
var_name + '" and "' + coda + '"'
end_pos = len(var_name)
if strict and star_pos != -1:
end_pos = star_pos
if var_name[0] == "#":
return self.vprefix + var_name[1:end_pos] + new_coda
else: # starts with -#
return "-" + self.vprefix + var_name[2:end_pos] + new_coda
else:
if strict:
assert not coda, "functional placeholders cannot " +\
'have scaling factors in strict mode'
first_hash_pos = var_name.find('#')
nums_strings = var_name[first_hash_pos+1:].split('#')
arg_str = '('
for num_str in nums_strings:
arg_str += self.vprefix + num_str + ', '
arg_str = arg_str[:-2] + ')'
return var_name[:first_hash_pos] + arg_str + coda
[docs] def print_aqasm_file(self):
"""
Prints aqasm file created by constructor.
Returns
-------
"""
with open(utg.preface(self.aqasm_path)) as f:
print(f.read())
if __name__ == "__main__":
def main():
print(5)
main()