def __init__(self, file_prefix, num_qbits): """ Constructor Parameters ---------- file_prefix : str file must be called file_prefix + '_' + num_qbits + "_eng.txt" num_qbits : int total number of qubits of circuit. Returns ------- """ self.file_prefix = file_prefix self.num_qbits = num_qbits self.english_in = open( utg.preface(file_prefix + '_' + str(num_qbits) + '_eng.txt'), 'rt') self.split_line = None self.tot_num_lines = 0 self.loop_to_start_offset = {} self.loop_to_start_line = {} self.loop_to_nreps = {} self.loop_queue = [] while not self.english_in.closed: self.scan_next_line()
def do_log(self): """ Write a log file and print info on console too. Returns ------- None """ log = open(utg.preface( self.file_prefix + '_' + str(self.num_bits) + '_log.txt'), 'wt') s = '' s += "Number of lines in file = " + str(self.tot_num_lines) + '\n' s += "Number of Elem. Ops = " + str(self.num_ops) + '\n' s += "Number of CNOTS (SIGX with single control) = " + \ str(self.num_cnots) + '\n' s += "List of distinct variable numbers encountered " s += "(length=" + str(len(self.vars_manager.all_var_nums)) + ')=\n' s += str(self.vars_manager.all_var_nums) + "\n" s += "List of distinct function names encountered " s += "(length=" + str(len(self.vars_manager.all_fun_names)) + ')=\n' s += str(self.vars_manager.all_fun_names) + "\n" log.write(s) if self.verbose: print(s) log.close()
def __init__(self, file_prefix, num_qbits, vars_manager=None, verbose=False, write_log=False, xfile_num=-1): """ Constructor Parameters ---------- file_prefix : str num_qbits : int vars_manager : PlaceholderManager verbose : bool write_log : bool xfile_num : int Returns ------- """ SEO_pre_reader.__init__(self, file_prefix, num_qbits) self.split_line = None self.vars_manager = vars_manager if vars_manager is None: self.vars_manager = PlaceholderManager() self.verbose = verbose self.write_log = write_log if write_log: self.vars_manager.eval_all_vars = False self.xfile_num = xfile_num if xfile_num >= 0: assert not self.vars_manager.var_num_to_rads, "we don't "\ "allow a var_num_to_rads and a loop xfile simultaneously" assert not self.vars_manager.fun_name_to_fun, "we don't "\ "allow a fun_name_to_fun and a loop xfile simultaneously" self.fill_history_lists_by_executing_loop_xfile() self.measured_bits = [] self.mcase_trols = None self.english_in = open( utg.preface(file_prefix + '_' + str(num_qbits) + '_eng.txt'), 'rt') self.loop_to_cur_rep = { loop_num: 0 for loop_num in self.loop_to_nreps.keys() } self.num_ops = 0 self.num_cnots = 0 self.line_count = 0 while not self.english_in.closed: self.next_line() if write_log: self.do_log()
def write_prelude(self): """ Writes PennyL opening statements before calls to use_ methods for gates. Returns ------- None """ vars_str = "" for num in self.all_var_nums: vars_str += self.vprefix + str(num) + ', ' vars_str = vars_str[:-2] s = 'import pennylane as qml\n\n\n' s += 'def ' + self.qnode_name + '(' + vars_str + '):\n' self.indentation += 4 s += ' ' * self.indentation s += '# distinct fun names in functional placeholders=\n' s += ' ' * self.indentation + '# ' s += str(self.all_fun_names) + '\n' if self.fun_defs_path: with open(utg.preface(self.fun_defs_path), 'r') as fi: fi_lines = fi.readlines() for line in fi_lines: s += ' ' * self.indentation + line s = s.rstrip() self.write(s)
def print_log_file(self): """ Prints log file. Returns ------- None """ path = self.get_log_file_path(rel=True) with open(utg.preface(path)) as f: print(f.read())
def __init__(self, file_prefix, emb, ZL=True, english_out=None, picture_out=None): """ Constructor Parameters ---------- file_prefix : str emb : CktEmbedder ZL : bool english_out : _io.TextIOWrapper picture_out : _io.TextIOWrapper Returns ------- """ self.gate_line_counter = 0 self.file_prefix = file_prefix self.emb = emb self.ZL = ZL self.measured_bits = [] if english_out is None and file_prefix: self.english_out = open(utg.preface(self.get_eng_file_path( rel=True)), 'wt') else: self.english_out = english_out if picture_out is None and file_prefix: self.picture_out = open(utg.preface(self.get_pic_file_path( rel=True)), 'wt') else: self.picture_out = picture_out self.indentation = 0
def get_log_file_path(self, rel=False): """ Returns path (relative if rel is True, absolute if rel is False) of log file Attributes ---------- rel : bool Returns ------- str """ rel_path = self.file_prefix + '_' + str(self.num_bits) + '_log.txt' return rel_path if rel else utg.preface(rel_path)
def fill_history_lists_by_executing_loop_xfile(self): """ This method is called by the constructor of this class, iff the user enters a valid (non-negative) xfile number. Before using this method, user is expected to have generated a Loop File from an English file via classes LoopFileGenerator and LoopyPlaceholderManager, and created a Loop xfile by editing that Loop File. This class executes the Loop xfile to fill its history dictionaries (the ones that end in _hist) Returns ------- None """ assert self.xfile_num >= 0, \ "user entered xfile number must be a non-negative int" all_var_nums = [] all_fun_names = [] var_num_to_hist = defaultdict(list) fun_name_to_hist = defaultdict(list) xfile_name = self.file_prefix + '_' + str(self.num_bits) +\ '_loop' + str(self.xfile_num) + '.py' try: loopx_in = open(utg.preface(xfile_name), 'rt') except IOError: print("Expected to find but didn't find a file named\n" + xfile_name) exit() # var_dict = \ # { # 'all_var_nums': all_var_nums, # 'all_fun_names': all_fun_names, # 'var_num_to_hist': var_num_to_hist, # 'fun_name_to_hist': fun_name_to_hist # } exec(loopx_in.read()) self.vars_manager.all_var_nums = all_var_nums self.vars_manager.all_fun_names = all_fun_names self.vars_manager.var_num_to_hist = var_num_to_hist self.vars_manager.fun_name_to_hist = fun_name_to_hist # print('--------before resolving') # print(all_var_nums, all_fun_names) # print(var_num_to_hist) # print(fun_name_to_hist) self.vars_manager.resolve_all_histories()
def get_pic_file_path(self, rel=False): """ Returns path (relative if rel is True, absolute if rel is False) of Picture file. Attributes ---------- rel : bool Returns ------- str """ rel_path = utg.get_pic_file_rel_path(self.file_prefix, self.emb.num_qbits_aft, ZL=self.ZL) return rel_path if rel else utg.preface(rel_path)
def get_eng_file_path(self, rel=False): """ Returns path (relative if rel is True, absolute if rel is False) of English file. Attributes ---------- rel : bool Returns ------- str """ rel_path = utg.get_eng_file_rel_path(self.file_prefix, self.emb.num_qbits_aft) # print("..,,mmmm", rel_path) return rel_path if rel else utg.preface(rel_path)
def print_pic_file(self, jup=False): """ Prints Picture file. Parameters ---------- jup : bool If jup=False, it prints text. Otherwise, it draws in a jupyter notebook a table with line numbers starting at 1 Returns ------- None """ with open(utg.preface(self.get_pic_file_path(rel=True)), 'r') as f: if not jup: print(f.read()) else: dis_obj = HTML(SEO_writer.gen_html_from_eng_or_pic_file(f)) display(dis_obj)
def get_mean_val(self, var_num_to_rads): """ This method returns a list partials_list consisting of 4 floats which are the partial derivatives wrt the 4 possible derivative directions ( deriv_direc), of the multi-controlled gate U specified by self.deriv_gate_str. Parameters ---------- var_num_to_rads : dict[int, float] Returns ------- list[float] """ partials_list = [0., 0., 0., 0.] # number of bits with (i.e., including) ancilla num_qbits_w_anc = self.num_qbits for has_neg_polarity, deriv_direc in it.product( *[[False, True], range(4)]): if self.deriv_gate_str == 'prior': if has_neg_polarity: has_neg_polarity = None else: continue # this skips iteration in loop for dpart_name in StairsDeriv.dpart_dict[deriv_direc]: emb = CktEmbedder(num_qbits_w_anc, num_qbits_w_anc) wr = StairsDerivCkt_writer(self.deriv_gate_str, has_neg_polarity, deriv_direc, dpart_name, self.gate_str_to_rads_list, self.file_prefix, emb) wr.close_files() # wr.print_pic_file() # wr.print_eng_file() t_list = self.gate_str_to_rads_list[self.deriv_gate_str] coef_of_dpart = StairsDerivCkt_writer.\ get_coef_of_dpart(t_list, deriv_direc, dpart_name, var_num_to_rads) fun_name_to_fun = StairsDerivCkt_writer.\ get_fun_name_to_fun(t_list, deriv_direc, dpart_name) vman = PlaceholderManager(var_num_to_rads=var_num_to_rads, fun_name_to_fun=fun_name_to_fun) # CGateExpander and the translator Qubiter_to_RigettiPyQuil # are both children of SEO_reader. SEO_reader and any of its # subclasses will accept a vman ( object of # PlaceholderManager) in one of its keyword args. If a # SEO_reader is given a vman as input, it will use it to # replace placeholder variable strings by floats. # PyQuil does not support multi-controlled u2 gates so # expand them to lowest common denominator, CNOTs and single # qubit gates, using CGateExpander. Give CGateExpander a # vman input so as to float all variables before expansion expan = CGateExpander(self.file_prefix, num_qbits_w_anc, vars_manager=vman) # this gives name of new file with expansion out_file_prefix = SEO_reader.xed_file_prefix(self.file_prefix) # expan.wr.print_pic_file() # expan.wr.print_eng_file() # this creates a file with all PyQuil gates that are # independent of hamil. self.translator = Qubiter_to_RigettiPyQuil( out_file_prefix, self.num_qbits, aqasm_name='RigPyQuil', prelude_str='', ending_str='') with open(utg.preface(self.translator.aqasm_path), 'r') as fi: self.translation_line_list = fi.readlines() pg = Program() for line in self.translation_line_list: line = line.strip('\n') if line: exec(line) len_pg_in = len(pg) for term, coef in self.hamil.terms.items(): # we have checked before that coef is real coef = complex(coef).real # print('nnnnnbbbbb', term) new_term = tuple(list(term) + [(num_qbits_w_anc - 1, 'X')]) # print('jjjjjjj', new_term) # Throw out previous coda. # Remember bug in Pyquil. Slicing a program turns it into # a list pg = Program(pg[:len_pg_in]) # add measurement coda for this term of hamil # and for X at ancilla bit_pos_to_xy_str =\ {bit: action for bit, action in new_term if action != 'Z'} RigettiTools.add_xy_meas_coda_to_program( pg, bit_pos_to_xy_str) # get effective state vec if self.num_samples: # send and receive from cloud, get obs_vec bitstrings = self.qc.run_and_measure( pg, trials=self.num_samples) obs_vec = RigettiTools.obs_vec_from_bitstrings( bitstrings, self.num_qbits, bs_is_array=False) # go from obs_vec to effective state vec counts_dict = StateVec.get_counts_from_obs_vec( self.num_qbits, obs_vec) emp_pd = StateVec.get_empirical_pd_from_counts( self.num_qbits, counts_dict) effective_st_vec = StateVec.\ get_emp_state_vec_from_emp_pd( self.num_qbits, emp_pd) else: # num_samples = 0 sim = WavefunctionSimulator() st_vec_arr = sim.wavefunction(pg).amplitudes st_vec_arr = st_vec_arr.reshape([2] * self.num_qbits) perm = list(reversed(range(self.num_qbits))) st_vec_arr = np.transpose(st_vec_arr, perm) effective_st_vec = StateVec(self.num_qbits, st_vec_arr) # add contribution to mean real_arr = self.get_real_vec(new_term) mean_val_change = coef*effective_st_vec.\ get_mean_value_of_real_diag_mat(real_arr) mean_val_change *= coef_of_dpart if has_neg_polarity: mean_val_change *= -1 partials_list[deriv_direc] += mean_val_change return partials_list
def __init__(self, qc, file_prefix, num_qbits, hamil, all_var_nums, fun_name_to_fun, do_resets=True, **kwargs): """ Constructor Do in constructor as much hamil indep stuff as possible so don't have to redo it with every call to cost fun. Also, when self.num_samples !=0, we store a dict called term_to_exec mapping an executable (output of Rigetti compile() function) to a term, for each term in the hamiltonian hamil. When num_samples=0, term_to_exec={} Parameters ---------- qc : QuantumComputer file_prefix : str num_qbits : int hamil : QubitOperator all_var_nums : list[int] fun_name_to_fun : dict[str, function] do_resets : bool kwargs : dict key-words args of MeanHamilMinimizer constructor Returns ------- """ MeanHamil.__init__(self, file_prefix, num_qbits, hamil, all_var_nums, fun_name_to_fun, **kwargs) self.qc = qc self.do_resets = do_resets # this creates a file with all PyQuil gates that # are independent of hamil. Gates may contain free parameters self.translator = Qubiter_to_RigettiPyQuil(self.file_prefix, self.num_qbits, aqasm_name='RigPyQuil', prelude_str='', ending_str='') with open(utg.preface(self.translator.aqasm_path), 'r') as fi: self.translation_line_list = fi.readlines() pg = Program() self.pg = pg if self.num_samples: # pg prelude pg += Pragma('INITIAL_REWIRING', ['"PARTIAL"']) if self.do_resets: pg += RESET() ro = pg.declare('ro', 'BIT', self.num_qbits) s = '' for var_num in self.all_var_nums: vname = self.translator.vprefix + str(var_num) s += vname s += ' = pg.declare("' s += vname s += '", memory_type="REAL")\n' exec(s) # add to pg the operations that are independent of hamil for line in self.translation_line_list: line = line.strip('\n') if line: exec(line) len_pg_in = len(pg) # hamil loop to store executables for each term in hamil self.term_to_exec = {} for term, coef in self.hamil.terms.items(): # reset pg to initial length. # Temporary work-around to bug # in PyQuil ver 2.5.0. # Slicing was changing # pg from type Program to type list pg = Program(pg[:len_pg_in]) self.pg = pg # add xy measurements coda to pg bit_pos_to_xy_str =\ {bit: action for bit, action in term if action != 'Z'} RigettiTools.add_xy_meas_coda_to_program(pg, bit_pos_to_xy_str) # request measurements for i in range(self.num_qbits): pg += MEASURE(i, ro[i]) pg.wrap_in_numshots_loop(shots=self.num_samples) executable = self.qc.compile(pg) # print(",,,...", executable) self.term_to_exec[term] = executable
def __init__(self, init_file_prefix, fin_file_prefix, num_qbits, ZL=True, fin_emb=None): """ Parameters ---------- init_file_prefix : str fin_file_prefix : str num_qbits : int ZL : bool fin_emb : CktEmbedder circuit embedder for the writer of the final English and Picture files Returns ------- """ assert init_file_prefix != fin_file_prefix,\ "intial and final file prefixes can't be the same." ZL_str = 'ZL' if ZL else 'ZF' def eng_path(file_prefix): return file_prefix +\ '_' + str(num_qbits) + '_eng.txt' def pic_path(file_prefix): return file_prefix +\ '_' + str(num_qbits) + '_' + ZL_str + 'pic.txt' init_eng_path = eng_path(init_file_prefix) fin_eng_path = eng_path(fin_file_prefix) self.fin_eng_path = fin_eng_path init_pic_path = pic_path(init_file_prefix) fin_pic_path = pic_path(fin_file_prefix) self.fin_pic_path = fin_pic_path # copying files try: copyfile(utg.preface(init_eng_path), utg.preface(fin_eng_path)) except: assert False, 'Could not copy file\n' + init_eng_path try: copyfile(utg.preface(init_pic_path), utg.preface(fin_pic_path)) except: assert False, 'Could not copy file\n' + init_pic_path # opening copies of files try: fin_eng_out = open(utg.preface(fin_eng_path), 'a') except: assert False, 'Could not open file\n' + fin_eng_path try: fin_pic_out = open(utg.preface(fin_pic_path), 'a') except: assert False, 'Could not open file\n' + fin_pic_path emb = CktEmbedder(num_qbits, num_qbits) if fin_emb: emb = fin_emb SEO_writer.__init__(self, fin_file_prefix, emb, ZL=ZL, english_out=fin_eng_out, picture_out=fin_pic_out)