Beispiel #1
0
    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()
Beispiel #2
0
    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()
Beispiel #3
0
    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)
Beispiel #5
0
    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())
Beispiel #6
0
    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
Beispiel #7
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)
Beispiel #8
0
    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()
Beispiel #9
0
    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)
Beispiel #10
0
    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)
Beispiel #11
0
    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)
Beispiel #12
0
    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
Beispiel #13
0
    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
Beispiel #14
0
    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)