Exemplo n.º 1
0
 def test_trivially_double_commutes_excess_create(self):
     self.assertTrue(
         trivially_double_commutes_dual_basis(FermionOperator('5^ 2'),
                                              FermionOperator('5^ 5'),
                                              FermionOperator('5^ 1')))
Exemplo n.º 2
0
 def test_trivially_double_commutes_excess_annihilate(self):
     self.assertTrue(
         trivially_double_commutes_dual_basis(FermionOperator('5^ 2'),
                                              FermionOperator('3^ 2'),
                                              FermionOperator('2^ 2')))
Exemplo n.º 3
0
 def test_trivially_double_commutes_double_annihilate_in_a_and_c(self):
     self.assertTrue(
         trivially_double_commutes_dual_basis(FermionOperator('5^ 2'),
                                              FermionOperator('3^ 1'),
                                              FermionOperator('4^ 1^ 4 1')))
Exemplo n.º 4
0
 def test_no_trivial_double_commute_double_annihilate_with_create(self):
     self.assertFalse(
         trivially_double_commutes_dual_basis(FermionOperator('5^ 2'),
                                              FermionOperator('2^ 1'),
                                              FermionOperator('4^ 2')))
Exemplo n.º 5
0
 def test_trivially_double_commutes_hopping_and_number_on_same_modes(self):
     self.assertTrue(
         trivially_double_commutes_dual_basis(FermionOperator('4^ 3'),
                                              FermionOperator('4^ 1'),
                                              FermionOperator('4^ 1^ 4 1')))
Exemplo n.º 6
0
 def test_trivially_double_commutes_no_intersection_a_with_bc(self):
     self.assertTrue(
         trivially_double_commutes_dual_basis(FermionOperator('5^ 2'),
                                              FermionOperator('3^ 1'),
                                              FermionOperator('4^ 1^ 4 1')))
Exemplo n.º 7
0
 def test_no_trivial_double_commute_left_hopping_operator(self):
     self.assertFalse(
         trivially_double_commutes_dual_basis(FermionOperator('4^ 3'),
                                              FermionOperator('3^ 2'),
                                              FermionOperator('3^ 3')))
Exemplo n.º 8
0
 def test_trivially_double_commutes_both_hopping_annihilate_same_mode(self):
     self.assertTrue(
         trivially_double_commutes_dual_basis(FermionOperator('1^ 1'),
                                              FermionOperator('4^ 1'),
                                              FermionOperator('3^ 1')))
Exemplo n.º 9
0
 def test_trivially_double_commutes_one_double_number_operators(self):
     self.assertTrue(
         trivially_double_commutes_dual_basis(FermionOperator('4^ 3'),
                                              FermionOperator('3^ 2^ 3 2'),
                                              FermionOperator('3^ 3')))
Exemplo n.º 10
0
 def test_trivially_double_commutes_nonintersecting_single_number_ops(self):
     self.assertTrue(
         trivially_double_commutes_dual_basis(FermionOperator('3^ 2'),
                                              FermionOperator('2^ 2'),
                                              FermionOperator('3^ 3')))
Exemplo n.º 11
0
 def test_no_trivial_double_commute_with_intersection(self):
     self.assertFalse(
         trivially_double_commutes_dual_basis(FermionOperator('4^ 2'),
                                              FermionOperator('2^ 1'),
                                              FermionOperator('5^ 2^ 5 2')))
Exemplo n.º 12
0
 def test_trivially_double_commutes_no_intersection(self):
     self.assertTrue(
         trivially_double_commutes_dual_basis(FermionOperator('3^ 4'),
                                              FermionOperator('3^ 2^ 3 2'),
                                              FermionOperator('4^ 1')))
Exemplo n.º 13
0
def low_depth_second_order_trotter_error_operator(terms,
                                                  indices=None,
                                                  is_hopping_operator=None,
                                                  jellium_only=False,
                                                  verbose=False):
    """Determine the difference between the exact generator of unitary
    evolution and the approximate generator given by the second-order
    Trotter-Suzuki expansion.

    Args:
        terms: a list of FermionOperators in the Hamiltonian in the
               order in which they will be simulated.
        indices: a set of indices the terms act on in the same order as terms.
        is_hopping_operator: a list of whether each term is a hopping operator.
        jellium_only: Whether the terms are from the jellium Hamiltonian only,
                      rather than the full dual basis Hamiltonian (i.e. whether
                      c_i = c for all number operators i^ i, or whether they
                      depend on i as is possible in the general case).
        verbose: Whether to print percentage progress.

    Returns:
        The difference between the true and effective generators of time
            evolution for a single Trotter step.

    Notes: follows Equation 9 of Poulin et al.'s work in "The Trotter Step
        Size Required for Accurate Quantum Simulation of Quantum Chemistry",
        applied to the "stagger"-based Trotter step for detailed in
        Kivlichan et al., "Quantum Simulation of Electronic Structure with
        Linear Depth and Connectivity", arxiv:1711.04789.
    """
    more_info = bool(indices)
    n_terms = len(terms)

    if verbose:
        import time
        start = time.time()

    error_operator = FermionOperator.zero()
    for beta in range(n_terms):
        if verbose and beta % (n_terms // 30) == 0:
            print('%4.3f percent done in' % ((float(beta) / n_terms)**3 * 100),
                  time.time() - start)

        for alpha in range(beta + 1):
            for alpha_prime in range(beta):
                # If we have pre-computed info on indices, use it to determine
                # trivial double commutation.
                if more_info:
                    if (not trivially_double_commutes_dual_basis_using_term_info(  # pylint: disable=C
                            indices[alpha], indices[beta],
                            indices[alpha_prime], is_hopping_operator[alpha],
                            is_hopping_operator[beta],
                            is_hopping_operator[alpha_prime], jellium_only)):
                        # Determine the result of the double commutator.
                        double_com = double_commutator(
                            terms[alpha], terms[beta], terms[alpha_prime],
                            indices[beta], indices[alpha_prime],
                            is_hopping_operator[beta],
                            is_hopping_operator[alpha_prime])
                        if alpha == beta:
                            double_com /= 2.0

                        error_operator += double_com

                # If we don't have more info, check for trivial double
                # commutation using the terms directly.
                elif not trivially_double_commutes_dual_basis(
                        terms[alpha], terms[beta], terms[alpha_prime]):
                    double_com = double_commutator(terms[alpha], terms[beta],
                                                   terms[alpha_prime])

                    if alpha == beta:
                        double_com /= 2.0

                    error_operator += double_com

    error_operator /= 12.0
    return error_operator