def test_error_operator(self):
        FO = FermionOperator

        terms = []
        for i in range(4):
            terms.append(FO(((i, 1), ((i + 1) % 4, 0)), -0.0123370055014))
            terms.append(FO(((i, 1), ((i - 1) % 4, 0)), -0.0123370055014))

            if i in [0, 2]:
                terms.append(
                    normal_ordered(
                        FO(((i + 1, 1), (i, 1), (i + 1, 0), (i, 0)),
                           3.18309886184)))
            if i < 2:
                terms.append(
                    normal_ordered(
                        FO(((i, 1), ((i + 2) % 4, 1), (i, 0),
                            ((i + 2) % 4, 0)), 22.2816920329)))

        self.assertAlmostEqual(
            low_depth_second_order_trotter_error_operator(terms).terms[((3, 1),
                                                                        (2, 1),
                                                                        (1, 1),
                                                                        (2, 0),
                                                                        (1, 0),
                                                                        (0,
                                                                         0))],
            0.75)
def double_commutator(op1,
                      op2,
                      op3,
                      indices2=None,
                      indices3=None,
                      is_hopping_operator2=None,
                      is_hopping_operator3=None):
    """Return the double commutator [op1, [op2, op3]].

    Args:
        op1, op2, op3 (FermionOperators or BosonOperators): operators for
            the commutator. All three operators must be of the same type.
        indices2, indices3 (set): The indices op2 and op3 act on.
        is_hopping_operator2 (bool): Whether op2 is a hopping operator.
        is_hopping_operator3 (bool): Whether op3 is a hopping operator.

    Returns:
        The double commutator of the given operators.
    """
    if is_hopping_operator2 and is_hopping_operator3:
        indices2 = set(indices2)
        indices3 = set(indices3)
        # Determine which indices both op2 and op3 act on.
        try:
            intersection, = indices2.intersection(indices3)
        except ValueError:
            return FermionOperator.zero()

        # Remove the intersection from the set of indices, since it will get
        # cancelled out in the final result.
        indices2.remove(intersection)
        indices3.remove(intersection)

        # Find the indices of the final output hopping operator.
        index2, = indices2
        index3, = indices3
        coeff2 = op2.terms[list(op2.terms)[0]]
        coeff3 = op3.terms[list(op3.terms)[0]]
        commutator23 = (FermionOperator(
            ((index2, 1), (index3, 0)), coeff2 * coeff3) + FermionOperator(
                ((index3, 1), (index2, 0)), -coeff2 * coeff3))
    else:
        commutator23 = normal_ordered(commutator(op2, op3))

    return normal_ordered(commutator(op1, commutator23))
    def test_sum_of_ordered_terms_equals_full_hamiltonian_odd_side_len(self):
        hamiltonian = normal_ordered(
            fermi_hubbard(5, 5, 1.0, -0.3, periodic=False))
        hamiltonian.compress()

        terms = simulation_ordered_grouped_hubbard_terms_with_info(
            hamiltonian)[0]
        terms_total = sum(terms, FermionOperator.zero())

        self.assertTrue(terms_total == hamiltonian)
    def test_total_length_odd_side_length_full_hubbard(self):
        hamiltonian = normal_ordered(
            fermi_hubbard(5, 5, -1., -0.3, periodic=False))
        hamiltonian.compress()

        # Unpack result into terms, indices they act on, and whether they're
        # hopping operators.
        result = simulation_ordered_grouped_hubbard_terms_with_info(
            hamiltonian)
        terms, _, _ = result

        self.assertEqual(len(terms), 105)
Exemple #5
0
    def test_total_length_even_side_length_onsite_only(self):
        hamiltonian = normal_ordered(
            fermi_hubbard(4, 4, 0., -0.3, periodic=False))
        hamiltonian.compress()

        # Unpack result into terms, indices they act on, and whether they're
        # hopping operators.
        result = simulation_ordered_grouped_hubbard_terms_with_info(
            hamiltonian)
        terms, indices, is_hopping = result

        self.assertEqual(len(terms), 16)
Exemple #6
0
    def get_qubit_expectations(self, qubit_operator):
        """Return expectations of QubitOperator in new QubitOperator.

        Args:
            qubit_operator: QubitOperator instance to be evaluated on
                this InteractionRDM.

        Returns:
            QubitOperator: QubitOperator with coefficients
            corresponding to expectation values of those operators.

        Raises:
            InteractionRDMError: Observable not contained in 1-RDM or 2-RDM.
        """
        from openfermion.transforms import reverse_jordan_wigner
        from openfermion.utils._operator_utils import normal_ordered
        qubit_operator_expectations = copy.deepcopy(qubit_operator)
        for qubit_term in qubit_operator_expectations.terms:
            expectation = 0.

            # Map qubits back to fermions.
            reversed_fermion_operators = reverse_jordan_wigner(
                QubitOperator(qubit_term))
            reversed_fermion_operators = normal_ordered(
                reversed_fermion_operators)

            # Loop through fermion terms.
            for fermion_term in reversed_fermion_operators.terms:
                coefficient = reversed_fermion_operators.terms[fermion_term]

                # Handle molecular term.
                if FermionOperator(
                        fermion_term).is_two_body_number_conserving():
                    if not fermion_term:
                        expectation += coefficient
                    else:
                        indices = [operator[0] for operator in fermion_term]
                        if len(indices) == 2:
                            # One-body term
                            indices = tuple(zip(indices, (1, 0)))
                        else:
                            # Two-body term
                            indices = tuple(zip(indices, (1, 1, 0, 0)))
                        rdm_element = self[indices]
                        expectation += rdm_element * coefficient

                # Handle non-molecular terms.
                elif len(fermion_term) > 4:
                    raise InteractionRDMError('Observable not contained '
                                              'in 1-RDM or 2-RDM.')
            qubit_operator_expectations.terms[qubit_term] = expectation
        return qubit_operator_expectations
    def test_sum_of_ordered_terms_equals_full_side_length_2_hopping_only(self):
        hamiltonian = normal_ordered(
            fermi_hubbard(2, 2, 1., 0.0, periodic=False))
        hamiltonian.compress()

        # Unpack result into terms, indices they act on, and whether they're
        # hopping operators.
        result = simulation_ordered_grouped_hubbard_terms_with_info(
            hamiltonian)
        terms, _, _ = result

        terms_total = sum(terms, FermionOperator.zero())

        self.assertTrue(terms_total == hamiltonian)
    def test_error_bound_using_info_even_side_length(self):
        # Generate the Hamiltonian.
        hamiltonian = normal_ordered(
            fermi_hubbard(4, 4, 0.5, 0.2, periodic=False))
        hamiltonian.compress()

        # Unpack result into terms, indices they act on, and whether they're
        # hopping operators.
        result = simulation_ordered_grouped_hubbard_terms_with_info(
            hamiltonian)
        terms, indices, is_hopping = result

        self.assertAlmostEqual(
            low_depth_second_order_trotter_error_bound(terms, indices,
                                                       is_hopping), 13.59)
    def test_is_hopping_operator_terms_with_info(self):
        hamiltonian = normal_ordered(
            fermi_hubbard(5, 5, 1., -1., periodic=False))
        hamiltonian.compress()

        # Unpack result into terms, indices they act on, and whether they're
        # hopping operators.
        result = simulation_ordered_grouped_hubbard_terms_with_info(
            hamiltonian)
        terms, _, is_hopping = result

        for i in range(len(terms)):
            single_term = list(terms[i].terms)[0]
            is_hopping_term = not (single_term[1][1]
                                   or single_term[0][0] == single_term[1][0])
            self.assertEqual(is_hopping_term, is_hopping[i])
    def test_correct_indices_terms_with_info(self):
        hamiltonian = normal_ordered(
            fermi_hubbard(5, 5, 1., -1., periodic=False))
        hamiltonian.compress()

        # Unpack result into terms, indices they act on, and whether they're
        # hopping operators.
        result = simulation_ordered_grouped_hubbard_terms_with_info(
            hamiltonian)
        terms, indices, _ = result

        for i in range(len(terms)):
            term = list(terms[i].terms)
            term_indices = set()
            for single_term in term:
                term_indices = term_indices.union(
                    [single_term[j][0] for j in range(len(single_term))])
            self.assertEqual(term_indices, indices[i])