Source code for qubiter.adv_applications.MeanHamil

from qubiter.StateVec import *
import qubiter.utilities_gen as utg
from qubiter.CodaSEO_writer import *
from qubiter.SEO_simulator import *
from qubiter.CktEmbedder import *
from openfermion.ops import QubitOperator


[docs]class MeanHamil: """ This is an abstract class. The main purpose of this class is to evaluate the mean value of a Hamiltonian. The Hamiltonian hamil is stored as an object of QubitOperator (a class of the open-source lib OpenFermion). `terms` is an attribute of QubitOperator. hamil.terms is a dictionary that maps a term to a coefficient. A term represents a tensor product of Pauli matrices (a Pauli string) as a tuple of tuples of the form (bit_pos, action). An example of a term: ( (1, 'X'), (2, 'Y')) file_prefix identifies the location of an English file that specifies a quantum circuit. If init_st_vec=None, we assume that the initial state of that quantum circuit is the ground state (all qubits in state ``|0>``). Let ``|psi>`` be the final state vector that evolves from that circuit. Let hamil be a Hamiltonian suitable for that circuit and stored as an object of QubitOperator (a class of the open-source lib OpenFermion). Then the mean value evaluated by this class is ``<psi|hamil|psi>``. Subclasses of this class use different methods to evaluate this mean value. They might change the tensor lib (numpy, PyTorch, TensorFlow) or the device (native, Rigetti, etc.) or the simulator for a particular device. They might evaluate the mean value exactly or empirically. Attributes ---------- all_var_nums : list[int] This is a list of all the non-functional placeholder variable numbers file_prefix : str Prefix to English file to be used in evaluating the mean hamil fun_name_to_fun : dict[str, function] This is a dict that maps function names to functions. Such functions are functional placeholders, meaning that their values are only decided at a later time. These functions do not vary during the minimization process. hamil : QubitOperator Hamiltonian init_st_vec : StateVec initial state vector num_qbits : int number of qubits num_samples : int number of samples (aka num_shots). If this is zero, the ``|psi>`` in ``<psi|H|psi>`` is calculated exactly from theory. If this is >0, the ``|psi>`` is calculated empirically from a number num_samples of "one-shot" experiments. simulator_name : str | None name of the simulator. """
[docs] def __init__(self, file_prefix, num_qbits, hamil, all_var_nums, fun_name_to_fun, init_st_vec=None, simulator_name=None, num_samples=0): """ Constructor Parameters ---------- file_prefix : str num_qbits : int hamil : QubitOperator all_var_nums : list[int] fun_name_to_fun : dict[str, function] init_st_vec : StateVec simulator_name : str num_samples : int Returns ------- """ self.file_prefix = file_prefix self.num_qbits = num_qbits self.hamil = hamil MeanHamil.check_hamil_is_herm(hamil) MeanHamil.check_hamil_is_in_range(hamil, num_qbits-1) self.all_var_nums = all_var_nums self.fun_name_to_fun = fun_name_to_fun self.init_st_vec = init_st_vec if self.init_st_vec is None: self.init_st_vec = StateVec.get_ground_st_vec(self.num_qbits) self.simulator_name = simulator_name self.num_samples = num_samples
[docs] @staticmethod def check_hamil_is_herm(hamil): """ Checks that the Hamiltonian hamil is a Hermitian operator. Emits warning and stops execution if it isn't. Parameters ---------- hamil : QubitOperator Returns ------- None """ for term, coef in hamil.terms.items(): coef = complex(coef) if abs(coef.imag) > 1e-8: assert False, 'The Hamiltonian should be Hermitian but it ' +\ "isn't. After being simplified by the " +\ 'BosonOperator constructor, ' +\ 'the coefficient of every term must be real.'
[docs] @staticmethod def check_hamil_is_in_range(hamil, max_bit_pos): """ Checks that the Hamiltonian hamil operates on range(max_bit_pos+1). Parameters ---------- hamil : QubitOperator max_bit_pos : int Returns ------- None """ for term, coef in hamil.terms.items(): for bit, action in term: assert bit in range(max_bit_pos+1)
[docs] def get_real_vec(self, term): """ Internal method that returns a numpy array, of shape [2]*num_qbits, that will be used as input to the method StateVec.get_mean_value_of_real_diag_mat() The input is a `term`. `terms` is an attribute of QubitOperator (a class in OpenFermion). terms is a dictionary that maps a term to a coefficient. A term represents a tensor product of Pauli matrices (a Pauli string) as a tuple of tuples of the form (bit_pos, action). An example of a term: ((1, 'X'), (2, 'Y')) Parameters ---------- term : tuple Returns ------- np.ndarray shape=[2]*num_qbits """ arr_plus = np.array([1., 1.]) arr_minus = np.array([1., -1.]) arr_list = [arr_plus]*self.num_qbits for bit_pos, action in term: arr_list[bit_pos] = arr_minus real_arr = utg.kron_prod(arr_list) real_arr = np.reshape(real_arr, tuple([2]*self.num_qbits)) return real_arr
[docs] def get_mean_val(self, var_num_to_rads): """ Abstract method. The main goal of subclasses of this class is to override this method. Parameters ---------- var_num_to_rads : dict[int, float] Returns ------- """ assert False