Ejemplo n.º 1
0
    def test_pauli_sgn_prod(self):
        p1 = Pauli(np.array([0]), np.array([1]))
        p2 = Pauli(np.array([1]), np.array([1]))

        self.log.info("sign product:")
        p3, sgn = sgn_prod(p1, p2)
        self.log.info("p1: %s", p1.to_label())
        self.log.info("p2: %s", p2.to_label())
        self.log.info("p3: %s", p3.to_label())
        self.log.info("sgn_prod(p1, p2): %s", str(sgn))
        self.assertEqual(p1.to_label(), 'X')
        self.assertEqual(p2.to_label(), 'Y')
        self.assertEqual(p3.to_label(), 'Z')
        self.assertEqual(sgn, 1j)

        self.log.info("sign product reverse:")
        p3, sgn = sgn_prod(p2, p1)
        self.log.info("p2: %s", p2.to_label())
        self.log.info("p1: %s", p1.to_label())
        self.log.info("p3: %s", p3.to_label())
        self.log.info("sgn_prod(p2, p1): %s", str(sgn))
        self.assertEqual(p1.to_label(), 'X')
        self.assertEqual(p2.to_label(), 'Y')
        self.assertEqual(p3.to_label(), 'Z')
        self.assertEqual(sgn, -1j)
Ejemplo n.º 2
0
    def test_pauli_sgn_prod(self):
        p1 = Pauli(np.array([0]), np.array([1]))
        p2 = Pauli(np.array([1]), np.array([1]))

        self.log.info("sign product:")
        p3, sgn = sgn_prod(p1, p2)
        self.log.info("p1: %s", p1.to_label())
        self.log.info("p2: %s", p2.to_label())
        self.log.info("p3: %s", p3.to_label())
        self.log.info("sgn_prod(p1, p2): %s", str(sgn))
        self.assertEqual(p1.to_label(), 'X')
        self.assertEqual(p2.to_label(), 'Y')
        self.assertEqual(p3.to_label(), 'Z')
        self.assertEqual(sgn, 1j)

        self.log.info("sign product reverse:")
        p3, sgn = sgn_prod(p2, p1)
        self.log.info("p2: %s", p2.to_label())
        self.log.info("p1: %s", p1.to_label())
        self.log.info("p3: %s", p3.to_label())
        self.log.info("sgn_prod(p2, p1): %s", str(sgn))
        self.assertEqual(p1.to_label(), 'X')
        self.assertEqual(p2.to_label(), 'Y')
        self.assertEqual(p3.to_label(), 'Z')
        self.assertEqual(sgn, -1j)
Ejemplo n.º 3
0
    def _two_body_mapping(h2_ijkm, a_i, a_j, a_k, a_m, threshold):
        """
        Subroutine for two body mapping.

        Args:
            h1_ijkm (complex): value of h2 at index (i,j,k,m)
            a_i (Pauli): pauli at index i
            a_j (Pauli): pauli at index j
            a_k (Pauli): pauli at index k
            a_m (Pauli): pauli at index m
            threshold: (float): threshold to remove a pauli

        Returns:
            Operator: Operator for those paulis
        """
        pauli_list = []
        for alpha in range(2):
            for beta in range(2):
                for gamma in range(2):
                    for delta in range(2):
                        pauli_prod_1 = sgn_prod(a_i[alpha], a_k[beta])
                        pauli_prod_2 = sgn_prod(pauli_prod_1[0], a_m[gamma])
                        pauli_prod_3 = sgn_prod(pauli_prod_2[0], a_j[delta])

                        phase1 = pauli_prod_1[1] * pauli_prod_2[
                            1] * pauli_prod_3[1]
                        phase2 = np.power(-1j, alpha + beta) * np.power(
                            1j, gamma + delta)
                        pauli_term = [
                            h2_ijkm / 16 * phase1 * phase2, pauli_prod_3[0]
                        ]
                        if np.absolute(pauli_term[0]) > threshold:
                            pauli_list.append(pauli_term)
        return Operator(paulis=pauli_list)
Ejemplo n.º 4
0
    def test_pauli(self):

        v = np.zeros(3)
        w = np.zeros(3)
        v[0] = 1
        w[1] = 1
        v[2] = 1
        w[2] = 1

        p = Pauli(v, w)
        self.log.info(p)
        self.log.info("In label form:")
        self.log.info(p.to_label())
        self.log.info("In matrix form:")
        self.log.info(p.to_matrix())


        q = random_pauli(2)
        self.log.info(q)

        r = inverse_pauli(p)
        self.log.info("In label form:")
        self.log.info(r.to_label())

        self.log.info("Group in tensor order:")
        grp = pauli_group(3, case=1)
        for j in grp:
            self.log.info(j.to_label())

        self.log.info("Group in weight order:")
        grp = pauli_group(3)
        for j in grp:
            self.log.info(j.to_label())

        self.log.info("sign product:")
        p1 = Pauli(np.array([0]), np.array([1]))
        p2 = Pauli(np.array([1]), np.array([1]))
        p3, sgn = sgn_prod(p1, p2)
        self.log.info(p1.to_label())
        self.log.info(p2.to_label())
        self.log.info(p3.to_label())
        self.log.info(sgn)

        self.log.info("sign product reverse:")
        p3, sgn = sgn_prod(p2, p1)
        self.log.info(p2.to_label())
        self.log.info(p1.to_label())
        self.log.info(p3.to_label())
        self.log.info(sgn)
Ejemplo n.º 5
0
    def test_pauli(self):

        v = np.zeros(3)
        w = np.zeros(3)
        v[0] = 1
        w[1] = 1
        v[2] = 1
        w[2] = 1

        p = Pauli(v, w)
        self.log.info(p)
        self.log.info("In label form:")
        self.log.info(p.to_label())
        self.log.info("In matrix form:")
        self.log.info(p.to_matrix())

        q = random_pauli(2)
        self.log.info(q)

        r = inverse_pauli(p)
        self.log.info("In label form:")
        self.log.info(r.to_label())

        self.log.info("Group in tensor order:")
        grp = pauli_group(3, case=1)
        for j in grp:
            self.log.info(j.to_label())

        self.log.info("Group in weight order:")
        grp = pauli_group(3)
        for j in grp:
            self.log.info(j.to_label())

        self.log.info("sign product:")
        p1 = Pauli(np.array([0]), np.array([1]))
        p2 = Pauli(np.array([1]), np.array([1]))
        p3, sgn = sgn_prod(p1, p2)
        self.log.info(p1.to_label())
        self.log.info(p2.to_label())
        self.log.info(p3.to_label())
        self.log.info(sgn)

        self.log.info("sign product reverse:")
        p3, sgn = sgn_prod(p2, p1)
        self.log.info(p2.to_label())
        self.log.info(p1.to_label())
        self.log.info(p3.to_label())
        self.log.info(sgn)
    def _one_body_mapping(h1_ij, a_i, a_j, threshold):
        """
        Subroutine for one body mapping.

        Args:
            h1_ij (complex): value of h1 at index (i,j)
            a_i (Pauli): pauli at index i
            a_j (Pauli): pauli at index j
            threshold: (float): threshold to remove a pauli

        Returns:
            Operator: Operator for those paulis
        """
        pauli_list = []
        for alpha in range(2):
            for beta in range(2):
                pauli_prod = sgn_prod(a_i[alpha], a_j[beta])
                coeff = h1_ij / 4 * pauli_prod[1] * np.power(-1j, alpha) * np.power(1j, beta)
                pauli_term = [coeff, pauli_prod[0]]
                if np.absolute(pauli_term[0]) > threshold:
                    pauli_list.append(pauli_term)
        return Operator(paulis=pauli_list)
Ejemplo n.º 7
0
def fermionic_maps(h1, h2, map_type, out_file=None, threshold=0.000000000001):
    """Creates a list of Paulis with coefficients from fermionic one and
    two-body operator.

    Args:
        h1 (list): second-quantized fermionic one-body operator
        h2 (list): second-quantized fermionic two-body operator
        map_type (str): "JORDAN_WIGNER", "PARITY", "BINARY_TREE"
        out_file (str): name of the optional file to write the Pauli list on
        threshold (float): threshold for Pauli simplification
    Returns:
        list: A list of Paulis with coefficients
    """
    # pylint: disable=invalid-name

    ####################################################################
    # ###########   DEFINING MAPPED FERMIONIC OPERATORS    #############
    ####################################################################

    pauli_list = []
    n = len(h1)  # number of fermionic modes / qubits
    a = []
    if map_type == 'JORDAN_WIGNER':
        for i in range(n):
            xv = np.append(np.append(np.ones(i), 0), np.zeros(n - i - 1))
            xw = np.append(np.append(np.zeros(i), 1), np.zeros(n - i - 1))
            yv = np.append(np.append(np.ones(i), 1), np.zeros(n - i - 1))
            yw = np.append(np.append(np.zeros(i), 1), np.zeros(n - i - 1))
            # defines the two mapped Pauli components of a_i and a_i^\dag,
            # according to a_i -> (a[i][0]+i*a[i][1])/2,
            # a_i^\dag -> (a_[i][0]-i*a[i][1])/2
            a.append((Pauli(xv, xw), Pauli(yv, yw)))
    if map_type == 'PARITY':
        for i in range(n):
            if i > 1:
                Xv = np.append(np.append(np.zeros(i - 1),
                                         [1, 0]), np.zeros(n - i - 1))
                Xw = np.append(np.append(np.zeros(i - 1),
                                         [0, 1]), np.ones(n - i - 1))
                Yv = np.append(np.append(np.zeros(i - 1),
                                         [0, 1]), np.zeros(n - i - 1))
                Yw = np.append(np.append(np.zeros(i - 1),
                                         [0, 1]), np.ones(n - i - 1))
            elif i > 0:
                Xv = np.append((1, 0), np.zeros(n - i - 1))
                Xw = np.append([0, 1], np.ones(n - i - 1))
                Yv = np.append([0, 1], np.zeros(n - i - 1))
                Yw = np.append([0, 1], np.ones(n - i - 1))
            else:
                Xv = np.append(0, np.zeros(n - i - 1))
                Xw = np.append(1, np.ones(n - i - 1))
                Yv = np.append(1, np.zeros(n - i - 1))
                Yw = np.append(1, np.ones(n - i - 1))
            # defines the two mapped Pauli components of a_i and a_i^\dag,
            # according to a_i -> (a[i][0]+i*a[i][1])/2,
            # a_i^\dag -> (a_[i][0]-i*a[i][1])/2
            a.append((Pauli(Xv, Xw), Pauli(Yv, Yw)))
    if map_type == 'BINARY_TREE':
        # FIND BINARY SUPERSET SIZE
        bin_sup = 1
        while n > np.power(2, bin_sup):
            bin_sup += 1
        # DEFINE INDEX SETS FOR EVERY FERMIONIC MODE
        update_sets = []
        update_pauli = []

        parity_sets = []
        parity_pauli = []

        flip_sets = []

        remainder_sets = []
        remainder_pauli = []
        for j in range(n):

            update_sets.append(update_set(j, np.power(2, bin_sup)))
            update_sets[j] = update_sets[j][update_sets[j] < n]

            parity_sets.append(parity_set(j, np.power(2, bin_sup)))
            parity_sets[j] = parity_sets[j][parity_sets[j] < n]

            flip_sets.append(flip_set(j, np.power(2, bin_sup)))
            flip_sets[j] = flip_sets[j][flip_sets[j] < n]

            remainder_sets.append(np.setdiff1d(parity_sets[j], flip_sets[j]))

            update_pauli.append(Pauli(np.zeros(n), np.zeros(n)))
            parity_pauli.append(Pauli(np.zeros(n), np.zeros(n)))
            remainder_pauli.append(Pauli(np.zeros(n), np.zeros(n)))
            for k in range(n):
                if np.in1d(k, update_sets[j]):
                    update_pauli[j].w[k] = 1
                if np.in1d(k, parity_sets[j]):
                    parity_pauli[j].v[k] = 1
                if np.in1d(k, remainder_sets[j]):
                    remainder_pauli[j].v[k] = 1

            x_j = Pauli(np.zeros(n), np.zeros(n))
            x_j.w[j] = 1
            y_j = Pauli(np.zeros(n), np.zeros(n))
            y_j.v[j] = 1
            y_j.w[j] = 1
            # defines the two mapped Pauli components of a_i and a_i^\dag,
            # according to a_i -> (a[i][0]+i*a[i][1])/2, a_i^\dag ->
            # (a_[i][0]-i*a[i][1])/2
            a.append((update_pauli[j] * x_j * parity_pauli[j],
                      update_pauli[j] * y_j * remainder_pauli[j]))

    ####################################################################
    # ###########    BUILDING THE MAPPED HAMILTONIAN     ###############
    ####################################################################

    # ######################    One-body    #############################
    for i in range(n):
        for j in range(n):
            if h1[i, j] != 0:
                for alpha in range(2):
                    for beta in range(2):
                        pauli_prod = sgn_prod(a[i][alpha], a[j][beta])
                        pauli_term = [h1[i, j] * 1 / 4 * pauli_prod[1] *
                                      np.power(-1j, alpha) *
                                      np.power(1j, beta),
                                      pauli_prod[0]]
                        pauli_list = pauli_term_append(
                            pauli_term, pauli_list, threshold)

    # ######################    Two-body    ############################
    for i in range(n):
        for j in range(n):
            for k in range(n):
                for m in range(n):
                    if h2[i, j, k, m] != 0:
                        for alpha in range(2):
                            for beta in range(2):
                                for gamma in range(2):
                                    for delta in range(2):
                                        # Note: chemists' notation for the
                                        # labeling,
                                        # h2(i,j,k,m) adag_i adag_k a_m a_j
                                        pauli_prod_1 = sgn_prod(
                                            a[i][alpha], a[k][beta])
                                        pauli_prod_2 = sgn_prod(
                                            pauli_prod_1[0], a[m][gamma])
                                        pauli_prod_3 = sgn_prod(
                                            pauli_prod_2[0], a[j][delta])

                                        phase1 = pauli_prod_1[1] *\
                                            pauli_prod_2[1] * pauli_prod_3[1]
                                        phase2 = np.power(-1j, alpha + beta) *\
                                            np.power(1j, gamma + delta)

                                        pauli_term = [
                                            h2[i, j, k, m] * 1 / 16 * phase1 *
                                            phase2, pauli_prod_3[0]]

                                        pauli_list = pauli_term_append(
                                            pauli_term, pauli_list, threshold)

    ####################################################################
    # ################          WRITE TO FILE         ##################
    ####################################################################

    if out_file is not None:
        out_stream = open(out_file, 'w')
        for pauli_term in pauli_list:
            out_stream.write(pauli_term[1].to_label() + '\n')
            out_stream.write('%.15f' % pauli_term[0].real + '\n')
        out_stream.close()
    return pauli_list
Ejemplo n.º 8
0
def fermionic_maps(h1,h2,map_type,out_file=None,threshold=0.000000000001):


    """ Takes fermionic one and two-body operators in the form of numpy arrays with real entries, e.g.
        h1=np.zeros((n,n))
        h2=np.zeros((n,n,n,n))
        where n is the number of fermionic modes, and gives a pauli_list of mapped pauli terms and
        coefficients, according to the map_type specified, with values

        map_type:
        JORDAN_WIGNER
        PARITY
        BINARY_TREE

        the notation for the two-body operator is the chemists' one,
        h2(i,j,k,m) a^dag_i a^dag_k a_m a_j

        Options:
        - writes the mapped pauli_list to a file named out_file given as an input (does not do this as default)
        - neglects mapped terms below a threshold defined by the user (default is 10^-12)

    """

    pauli_list=[]

    n=len(h1) # number of fermionic modes / qubits

    """
    ####################################################################
    ############   DEFINING MAPPED FERMIONIC OPERATORS    ##############
    ####################################################################
    """

    a=[]

    if map_type=='JORDAN_WIGNER':

        for i in range(n):


            Xv=np.append(np.append(np.ones(i),0),np.zeros(n-i-1))
            Xw=np.append(np.append(np.zeros(i),1),np.zeros(n-i-1))
            Yv=np.append(np.append(np.ones(i),1),np.zeros(n-i-1))
            Yw=np.append(np.append(np.zeros(i),1),np.zeros(n-i-1))

            # defines the two mapped Pauli components of a_i and a_i^\dag, according to a_i -> (a[i][0]+i*a[i][1])/2, a_i^\dag -> (a_[i][0]-i*a[i][1])/2
            a.append((Pauli(Xv,Xw),Pauli(Yv,Yw)))


    if map_type=='PARITY':

        for i in range(n):

            if i>1:

                Xv=np.append(np.append(np.zeros(i-1),[1,0]),np.zeros(n-i-1))
                Xw=np.append(np.append(np.zeros(i-1),[0,1]),np.ones(n-i-1))
                Yv=np.append(np.append(np.zeros(i-1),[0,1]),np.zeros(n-i-1))
                Yw=np.append(np.append(np.zeros(i-1),[0,1]),np.ones(n-i-1))

            elif i>0:

                Xv=np.append((1,0),np.zeros(n-i-1))
                Xw=np.append([0,1],np.ones(n-i-1))
                Yv=np.append([0,1],np.zeros(n-i-1))
                Yw=np.append([0,1],np.ones(n-i-1))

            else:

                Xv=np.append(0,np.zeros(n-i-1))
                Xw=np.append(1,np.ones(n-i-1))
                Yv=np.append(1,np.zeros(n-i-1))
                Yw=np.append(1,np.ones(n-i-1))

            # defines the two mapped Pauli components of a_i and a_i^\dag, according to a_i -> (a[i][0]+i*a[i][1])/2, a_i^\dag -> (a_[i][0]-i*a[i][1])/2
            a.append((Pauli(Xv,Xw),Pauli(Yv,Yw)))


    if map_type=='BINARY_TREE':


        # FIND BINARY SUPERSET SIZE

        bin_sup=1
        while n>np.power(2,bin_sup):
            bin_sup+=1

        # DEFINE INDEX SETS FOR EVERY FERMIONIC MODE

        update_sets=[]
        update_pauli=[]

        parity_sets=[]
        parity_pauli=[]

        flip_sets=[]
        flip_pauli=[]

        remainder_sets=[]
        remainder_pauli=[]


        for j in range(n):

            update_sets.append(update_set(j,np.power(2,bin_sup)))
            update_sets[j]=update_sets[j][update_sets[j]<n]

            parity_sets.append(parity_set(j,np.power(2,bin_sup)))
            parity_sets[j]=parity_sets[j][parity_sets[j]<n]

            flip_sets.append(flip_set(j,np.power(2,bin_sup)))
            flip_sets[j]=flip_sets[j][flip_sets[j]<n]

            remainder_sets.append(np.setdiff1d(parity_sets[j],flip_sets[j]))




            update_pauli.append(Pauli(np.zeros(n),np.zeros(n)))
            parity_pauli.append(Pauli(np.zeros(n),np.zeros(n)))
            remainder_pauli.append(Pauli(np.zeros(n),np.zeros(n)))

            for k in range(n):

                if np.in1d(k,update_sets[j]):

                    update_pauli[j].w[k]=1

                if np.in1d(k,parity_sets[j]):

                    parity_pauli[j].v[k]=1

                if np.in1d(k,remainder_sets[j]):

                    remainder_pauli[j].v[k]=1

            Xj=Pauli(np.zeros(n),np.zeros(n))
            Xj.w[j]=1
            Yj=Pauli(np.zeros(n),np.zeros(n))
            Yj.v[j]=1
            Yj.w[j]=1

            # defines the two mapped Pauli components of a_i and a_i^\dag, according to a_i -> (a[i][0]+i*a[i][1])/2, a_i^\dag -> (a_[i][0]-i*a[i][1])/2
            a.append((update_pauli[j]*Xj*parity_pauli[j],update_pauli[j]*Yj*remainder_pauli[j]))


    """
    ####################################################################
    ############    BUILDING THE MAPPED HAMILTONIAN     ################
    ####################################################################
    """


    """
    #######################    One-body    #############################
    """

    for i in range(n):
        for j in range(n):
            if h1[i,j]!=0:
                for alpha in range(2):
                    for beta in range(2):

                            pauli_prod=sgn_prod(a[i][alpha],a[j][beta])
                            pauli_term=[  h1[i,j]*1/4*pauli_prod[1]*np.power(-1j,alpha)*np.power(1j,beta),  pauli_prod[0]  ]
                            pauli_list=pauli_term_append(pauli_term,pauli_list,threshold)



    """
    #######################    Two-body    #############################
    """

    for i in range(n):
        for j in range(n):
            for k in range(n):
                for m in range(n):

                    if h2[i,j,k,m]!=0:

                        for alpha in range(2):
                            for beta in range(2):
                                for gamma in range(2):
                                    for delta in range(2):

                                        """
                                        # Note: chemists' notation for the labeling, h2(i,j,k,m) adag_i adag_k a_m a_j
                                        """

                                        pauli_prod_1=sgn_prod(a[i][alpha],a[k][beta])
                                        pauli_prod_2=sgn_prod(pauli_prod_1[0],a[m][gamma])
                                        pauli_prod_3=sgn_prod(pauli_prod_2[0],a[j][delta])

                                        phase1=pauli_prod_1[1]*pauli_prod_2[1]*pauli_prod_3[1]
                                        phase2=np.power(-1j,alpha+beta)*np.power(1j,gamma+delta)

                                        pauli_term=[h2[i,j,k,m]*1/16*phase1*phase2,pauli_prod_3[0]]

                                        pauli_list=pauli_term_append(pauli_term,pauli_list,threshold)


    """
    ####################################################################
    #################          WRITE TO FILE         ###################
    ####################################################################
    """


    if out_file!= None:
        out_stream=open(out_file,'w')

        for pauli_term in pauli_list:
            out_stream.write(pauli_term[1].to_label()+'\n')
            out_stream.write('%.15f' % pauli_term[0].real+'\n')

        out_stream.close()

    return pauli_list
Ejemplo n.º 9
0
def fermionic_maps(h1, h2, map_type, out_file=None, threshold=0.000000000001):
    """Creates a list of Paulis with coefficients from fermionic one and
    two-body operator.

    Args:
        h1 (list): second-quantized fermionic one-body operator
        h2 (list): second-quantized fermionic two-body operator
        map_type (str): "JORDAN_WIGNER", "PARITY", "BINARY_TREE"
        out_file (str): name of the optional file to write the Pauli list on
        threshold (float): threshold for Pauli simplification
    Returns:
        list: A list of Paulis with coefficients
    """
    # pylint: disable=invalid-name

    ####################################################################
    # ###########   DEFINING MAPPED FERMIONIC OPERATORS    #############
    ####################################################################

    pauli_list = []
    n = len(h1)  # number of fermionic modes / qubits
    a = []
    if map_type == 'JORDAN_WIGNER':
        for i in range(n):
            xv = np.append(np.append(np.ones(i), 0), np.zeros(n - i - 1))
            xw = np.append(np.append(np.zeros(i), 1), np.zeros(n - i - 1))
            yv = np.append(np.append(np.ones(i), 1), np.zeros(n - i - 1))
            yw = np.append(np.append(np.zeros(i), 1), np.zeros(n - i - 1))
            # defines the two mapped Pauli components of a_i and a_i^\dag,
            # according to a_i -> (a[i][0]+i*a[i][1])/2,
            # a_i^\dag -> (a_[i][0]-i*a[i][1])/2
            a.append((Pauli(xv, xw), Pauli(yv, yw)))
    if map_type == 'PARITY':
        for i in range(n):
            if i > 1:
                Xv = np.append(np.append(np.zeros(i - 1),
                                         [1, 0]), np.zeros(n - i - 1))
                Xw = np.append(np.append(np.zeros(i - 1),
                                         [0, 1]), np.ones(n - i - 1))
                Yv = np.append(np.append(np.zeros(i - 1),
                                         [0, 1]), np.zeros(n - i - 1))
                Yw = np.append(np.append(np.zeros(i - 1),
                                         [0, 1]), np.ones(n - i - 1))
            elif i > 0:
                Xv = np.append((1, 0), np.zeros(n - i - 1))
                Xw = np.append([0, 1], np.ones(n - i - 1))
                Yv = np.append([0, 1], np.zeros(n - i - 1))
                Yw = np.append([0, 1], np.ones(n - i - 1))
            else:
                Xv = np.append(0, np.zeros(n - i - 1))
                Xw = np.append(1, np.ones(n - i - 1))
                Yv = np.append(1, np.zeros(n - i - 1))
                Yw = np.append(1, np.ones(n - i - 1))
            # defines the two mapped Pauli components of a_i and a_i^\dag,
            # according to a_i -> (a[i][0]+i*a[i][1])/2,
            # a_i^\dag -> (a_[i][0]-i*a[i][1])/2
            a.append((Pauli(Xv, Xw), Pauli(Yv, Yw)))
    if map_type == 'BINARY_TREE':
        # FIND BINARY SUPERSET SIZE
        bin_sup = 1
        while n > np.power(2, bin_sup):
            bin_sup += 1
        # DEFINE INDEX SETS FOR EVERY FERMIONIC MODE
        update_sets = []
        update_pauli = []

        parity_sets = []
        parity_pauli = []

        flip_sets = []

        remainder_sets = []
        remainder_pauli = []
        for j in range(n):

            update_sets.append(update_set(j, np.power(2, bin_sup)))
            update_sets[j] = update_sets[j][update_sets[j] < n]

            parity_sets.append(parity_set(j, np.power(2, bin_sup)))
            parity_sets[j] = parity_sets[j][parity_sets[j] < n]

            flip_sets.append(flip_set(j, np.power(2, bin_sup)))
            flip_sets[j] = flip_sets[j][flip_sets[j] < n]

            remainder_sets.append(np.setdiff1d(parity_sets[j], flip_sets[j]))

            update_pauli.append(Pauli(np.zeros(n), np.zeros(n)))
            parity_pauli.append(Pauli(np.zeros(n), np.zeros(n)))
            remainder_pauli.append(Pauli(np.zeros(n), np.zeros(n)))
            for k in range(n):
                if np.in1d(k, update_sets[j]):
                    update_pauli[j].w[k] = 1
                if np.in1d(k, parity_sets[j]):
                    parity_pauli[j].v[k] = 1
                if np.in1d(k, remainder_sets[j]):
                    remainder_pauli[j].v[k] = 1

            x_j = Pauli(np.zeros(n), np.zeros(n))
            x_j.w[j] = 1
            y_j = Pauli(np.zeros(n), np.zeros(n))
            y_j.v[j] = 1
            y_j.w[j] = 1
            # defines the two mapped Pauli components of a_i and a_i^\dag,
            # according to a_i -> (a[i][0]+i*a[i][1])/2, a_i^\dag ->
            # (a_[i][0]-i*a[i][1])/2
            a.append((update_pauli[j] * x_j * parity_pauli[j],
                      update_pauli[j] * y_j * remainder_pauli[j]))

    ####################################################################
    # ###########    BUILDING THE MAPPED HAMILTONIAN     ###############
    ####################################################################

    # ######################    One-body    #############################
    for i in range(n):
        for j in range(n):
            if h1[i, j] != 0:
                for alpha in range(2):
                    for beta in range(2):
                        pauli_prod = sgn_prod(a[i][alpha], a[j][beta])
                        pauli_term = [h1[i, j] * 1 / 4 * pauli_prod[1] *
                                      np.power(-1j, alpha) *
                                      np.power(1j, beta),
                                      pauli_prod[0]]
                        pauli_list = pauli_term_append(
                            pauli_term, pauli_list, threshold)

    # ######################    Two-body    ############################
    for i in range(n):
        for j in range(n):
            for k in range(n):
                for m in range(n):
                    if h2[i, j, k, m] != 0:
                        for alpha in range(2):
                            for beta in range(2):
                                for gamma in range(2):
                                    for delta in range(2):
                                        # Note: chemists' notation for the
                                        # labeling,
                                        # h2(i,j,k,m) adag_i adag_k a_m a_j
                                        pauli_prod_1 = sgn_prod(
                                            a[i][alpha], a[k][beta])
                                        pauli_prod_2 = sgn_prod(
                                            pauli_prod_1[0], a[m][gamma])
                                        pauli_prod_3 = sgn_prod(
                                            pauli_prod_2[0], a[j][delta])

                                        phase1 = pauli_prod_1[1] *\
                                            pauli_prod_2[1] * pauli_prod_3[1]
                                        phase2 = np.power(-1j, alpha + beta) *\
                                            np.power(1j, gamma + delta)

                                        pauli_term = [
                                            h2[i, j, k, m] * 1 / 16 * phase1 *
                                            phase2, pauli_prod_3[0]]

                                        pauli_list = pauli_term_append(
                                            pauli_term, pauli_list, threshold)

    ####################################################################
    # ################          WRITE TO FILE         ##################
    ####################################################################

    if out_file is not None:
        out_stream = open(out_file, 'w')
        for pauli_term in pauli_list:
            out_stream.write(pauli_term[1].to_label() + '\n')
            out_stream.write('%.15f' % pauli_term[0].real + '\n')
        out_stream.close()
    return pauli_list
Ejemplo n.º 10
0
def fermionic_maps(h1, h2, map_type, out_file=None, threshold=0.000000000001):
    """ Takes fermionic one and two-body operators in the form of numpy arrays with real entries, e.g.
        h1=np.zeros((n,n))
        h2=np.zeros((n,n,n,n))
        where n is the number of fermionic modes, and gives a pauli_list of mapped pauli terms and
        coefficients, according to the map_type specified, with values

        map_type:
        JORDAN_WIGNER
        PARITY
        BINARY_TREE

        the notation for the two-body operator is the chemists' one,
        h2(i,j,k,m) a^dag_i a^dag_k a_m a_j

        Options:
        - writes the mapped pauli_list to a file named out_file given as an input (does not do this as default)
        - neglects mapped terms below a threshold defined by the user (default is 10^-12)

    """

    pauli_list = []

    n = len(h1)  # number of fermionic modes / qubits
    """
    ####################################################################
    ############   DEFINING MAPPED FERMIONIC OPERATORS    ##############
    ####################################################################
    """

    a = []

    if map_type == 'JORDAN_WIGNER':

        for i in range(n):

            Xv = np.append(np.append(np.ones(i), 0), np.zeros(n - i - 1))
            Xw = np.append(np.append(np.zeros(i), 1), np.zeros(n - i - 1))
            Yv = np.append(np.append(np.ones(i), 1), np.zeros(n - i - 1))
            Yw = np.append(np.append(np.zeros(i), 1), np.zeros(n - i - 1))

            # defines the two mapped Pauli components of a_i and a_i^\dag, according to a_i -> (a[i][0]+i*a[i][1])/2, a_i^\dag -> (a_[i][0]-i*a[i][1])/2
            a.append((Pauli(Xv, Xw), Pauli(Yv, Yw)))

    if map_type == 'PARITY':

        for i in range(n):

            if i > 1:

                Xv = np.append(np.append(np.zeros(i - 1), [1, 0]),
                               np.zeros(n - i - 1))
                Xw = np.append(np.append(np.zeros(i - 1), [0, 1]),
                               np.ones(n - i - 1))
                Yv = np.append(np.append(np.zeros(i - 1), [0, 1]),
                               np.zeros(n - i - 1))
                Yw = np.append(np.append(np.zeros(i - 1), [0, 1]),
                               np.ones(n - i - 1))

            elif i > 0:

                Xv = np.append((1, 0), np.zeros(n - i - 1))
                Xw = np.append([0, 1], np.ones(n - i - 1))
                Yv = np.append([0, 1], np.zeros(n - i - 1))
                Yw = np.append([0, 1], np.ones(n - i - 1))

            else:

                Xv = np.append(0, np.zeros(n - i - 1))
                Xw = np.append(1, np.ones(n - i - 1))
                Yv = np.append(1, np.zeros(n - i - 1))
                Yw = np.append(1, np.ones(n - i - 1))

            # defines the two mapped Pauli components of a_i and a_i^\dag, according to a_i -> (a[i][0]+i*a[i][1])/2, a_i^\dag -> (a_[i][0]-i*a[i][1])/2
            a.append((Pauli(Xv, Xw), Pauli(Yv, Yw)))

    if map_type == 'BINARY_TREE':

        # FIND BINARY SUPERSET SIZE

        bin_sup = 1
        while n > np.power(2, bin_sup):
            bin_sup += 1

        # DEFINE INDEX SETS FOR EVERY FERMIONIC MODE

        update_sets = []
        update_pauli = []

        parity_sets = []
        parity_pauli = []

        flip_sets = []
        flip_pauli = []

        remainder_sets = []
        remainder_pauli = []

        for j in range(n):

            update_sets.append(update_set(j, np.power(2, bin_sup)))
            update_sets[j] = update_sets[j][update_sets[j] < n]

            parity_sets.append(parity_set(j, np.power(2, bin_sup)))
            parity_sets[j] = parity_sets[j][parity_sets[j] < n]

            flip_sets.append(flip_set(j, np.power(2, bin_sup)))
            flip_sets[j] = flip_sets[j][flip_sets[j] < n]

            remainder_sets.append(np.setdiff1d(parity_sets[j], flip_sets[j]))

            update_pauli.append(Pauli(np.zeros(n), np.zeros(n)))
            parity_pauli.append(Pauli(np.zeros(n), np.zeros(n)))
            remainder_pauli.append(Pauli(np.zeros(n), np.zeros(n)))

            for k in range(n):

                if np.in1d(k, update_sets[j]):

                    update_pauli[j].w[k] = 1

                if np.in1d(k, parity_sets[j]):

                    parity_pauli[j].v[k] = 1

                if np.in1d(k, remainder_sets[j]):

                    remainder_pauli[j].v[k] = 1

            Xj = Pauli(np.zeros(n), np.zeros(n))
            Xj.w[j] = 1
            Yj = Pauli(np.zeros(n), np.zeros(n))
            Yj.v[j] = 1
            Yj.w[j] = 1

            # defines the two mapped Pauli components of a_i and a_i^\dag, according to a_i -> (a[i][0]+i*a[i][1])/2, a_i^\dag -> (a_[i][0]-i*a[i][1])/2
            a.append((update_pauli[j] * Xj * parity_pauli[j],
                      update_pauli[j] * Yj * remainder_pauli[j]))
    """
    ####################################################################
    ############    BUILDING THE MAPPED HAMILTONIAN     ################
    ####################################################################
    """
    """
    #######################    One-body    #############################
    """

    for i in range(n):
        for j in range(n):
            if h1[i, j] != 0:
                for alpha in range(2):
                    for beta in range(2):

                        pauli_prod = sgn_prod(a[i][alpha], a[j][beta])
                        pauli_term = [
                            h1[i, j] * 1 / 4 * pauli_prod[1] *
                            np.power(-1j, alpha) * np.power(1j, beta),
                            pauli_prod[0]
                        ]
                        pauli_list = pauli_term_append(pauli_term, pauli_list,
                                                       threshold)
    """
    #######################    Two-body    #############################
    """

    for i in range(n):
        for j in range(n):
            for k in range(n):
                for m in range(n):

                    if h2[i, j, k, m] != 0:

                        for alpha in range(2):
                            for beta in range(2):
                                for gamma in range(2):
                                    for delta in range(2):
                                        """
                                        # Note: chemists' notation for the labeling, h2(i,j,k,m) adag_i adag_k a_m a_j
                                        """

                                        pauli_prod_1 = sgn_prod(
                                            a[i][alpha], a[k][beta])
                                        pauli_prod_2 = sgn_prod(
                                            pauli_prod_1[0], a[m][gamma])
                                        pauli_prod_3 = sgn_prod(
                                            pauli_prod_2[0], a[j][delta])

                                        phase1 = pauli_prod_1[1] * pauli_prod_2[
                                            1] * pauli_prod_3[1]
                                        phase2 = np.power(
                                            -1j, alpha + beta) * np.power(
                                                1j, gamma + delta)

                                        pauli_term = [
                                            h2[i, j, k, m] * 1 / 16 * phase1 *
                                            phase2, pauli_prod_3[0]
                                        ]

                                        pauli_list = pauli_term_append(
                                            pauli_term, pauli_list, threshold)
    """
    ####################################################################
    #################          WRITE TO FILE         ###################
    ####################################################################
    """

    if out_file != None:
        out_stream = open(out_file, 'w')

        for pauli_term in pauli_list:
            out_stream.write(pauli_term[1].to_label() + '\n')
            out_stream.write('%.15f' % pauli_term[0].real + '\n')

        out_stream.close()

    return pauli_list