Beispiel #1
0
    def test_zero_coeff(self):
        """
            test addition
        """
        pauli_a = 'IXYZ'
        pauli_b = 'IXYZ'
        coeff_a = 0.5
        coeff_b = -0.5
        pauli_term_a = [coeff_a, label_to_pauli(pauli_a)]
        pauli_term_b = [coeff_b, label_to_pauli(pauli_b)]
        opA = Operator(paulis=[pauli_term_a])
        opB = Operator(paulis=[pauli_term_b])
        newOP = opA + opB
        newOP.zeros_coeff_elimination()

        self.assertEqual(0, len(newOP.paulis),
                         "{}".format(newOP.print_operators()))

        paulis = ['IXYZ', 'XXZY', 'IIZZ', 'XXYY', 'ZZXX', 'YYYY']
        coeffs = [0.2, 0.6, 0.8, -0.2, -0.6, -0.8]
        op = Operator(paulis=[])
        for coeff, pauli in zip(coeffs, paulis):
            pauli_term = [coeff, label_to_pauli(pauli)]
            op += Operator(paulis=[pauli_term])

        for i in range(6):
            opA = Operator(paulis=[[-coeffs[i], label_to_pauli(paulis[i])]])
            op += opA
            op.zeros_coeff_elimination()
            self.assertEqual(6 - (i + 1), len(op.paulis))
Beispiel #2
0
    def test_zero_elimination(self):
        pauli_a = 'IXYZ'
        coeff_a = 0.0
        pauli_term_a = [coeff_a, label_to_pauli(pauli_a)]
        opA = Operator(paulis=[pauli_term_a])
        self.assertEqual(1, len(opA.paulis), "{}".format(opA.print_operators()))
        opA.zeros_coeff_elimination()

        self.assertEqual(0, len(opA.paulis), "{}".format(opA.print_operators()))
Beispiel #3
0
def bksf_mapping(fer_op):
    """
    Transform from InteractionOpeator to QubitOperator for Bravyi-Kitaev fast algorithm.

    The electronic Hamiltonian is represented in terms of creation and
    annihilation operators. These creation and annihilation operators could be
    used to define Majorana modes as follows:
        c_{2i} = a_i + a^{\dagger}_i,
        c_{2i+1} = (a_i - a^{\dagger}_{i})/(1j)
    These Majorana modes can be used to define edge operators B_i and A_{ij}:
        B_i=c_{2i}c_{2i+1},
        A_{ij}=c_{2i}c_{2j}
    using these edge operators the fermionic algebra can be generated and
    hence all the terms in the electronic Hamiltonian can be expressed in
    terms of edge operators. The terms in electronic Hamiltonian can be
    divided into five types (arXiv 1208.5986). We can find the edge operator
    expression for each of those five types. For example, the excitation
    operator term in Hamiltonian when represented in terms of edge operators
    becomes:
        a_i^{\dagger}a_j+a_j^{\dagger}a_i = (-1j/2)*(A_ij*B_i+B_j*A_ij)
    For the sake of brevity the reader is encouraged to look up the
    expressions of other terms from the code below. The variables for edge
    operators are chosen according to the nomenclature defined above
    (B_i and A_ij). A detailed description of these operators and the terms
    of the electronic Hamiltonian are provided in (arXiv 1712.00446).

    Args:
        fer_op (FermionicOperator): the fermionic operator in the second quanitzed form

    Returns:
        Operator: mapped qubit operator
    """
    fer_op = copy.deepcopy(fer_op)
    # bksf mapping works with the 'physicist' notation.
    fer_op.h2 = np.einsum('ijkm->ikmj', fer_op.h2)
    modes = fer_op.modes
    # Initialize qubit operator as constant.
    qubit_op = Operator(paulis=[])
    edge_list = bravyi_kitaev_fast_edge_list(fer_op)
    # Loop through all indices.
    for p in range(modes):
        for q in range(modes):
            # Handle one-body terms.
            h1_pq = fer_op.h1[p, q]

            if h1_pq != 0.0 and p >= q:
                qubit_op += _one_body(edge_list, p, q, h1_pq)

            # Keep looping for the two-body terms.
            for r in range(modes):
                for s in range(modes):
                    h2_pqrs = fer_op.h2[p, q, r, s]

                    # Skip zero terms.
                    if (h2_pqrs == 0.0) or (p == q) or (r == s):
                        continue

                    # Identify and skip one of the complex conjugates.
                    if [p, q, r, s] != [s, r, q, p]:
                        if len(set([p, q, r, s])) == 4:
                            if min(r, s) < min(p, q):
                                continue
                        # Handle case of 3 unique indices
                        elif len(set([p, q, r, s])) == 3:
                            qubit_op += _two_body(edge_list, p, q, r, s,
                                                  0.5 * h2_pqrs)
                            continue
                        elif p != r and q < p:
                            continue

                    qubit_op += _two_body(edge_list, p, q, r, s, h2_pqrs)

    qubit_op.zeros_coeff_elimination()
    return qubit_op