def benchmark_fermion_math_and_normal_order(n_qubits, term_length, power):
    """Benchmark both arithmetic operators and normal ordering on fermions.

    The idea is we generate two random FermionTerms, A and B, each acting
    on n_qubits with term_length operators. We then compute
    (A + B) ** power. This is costly that is the first benchmark. The second
    benchmark is in normal ordering whatever comes out.

    Args:
        n_qubits: The number of qubits on which these terms act.
        term_length: The number of operators in each term.
        power: Int, the exponent to which to raise sum of the two terms.

    Returns:
        runtime_math: The time it takes to perform (A + B) ** power
        runtime_normal_order: The time it takes to perform
            FermionOperator.normal_order()
    """
    # Generate random operator strings.
    operators_a = [(numpy.random.randint(n_qubits),
                    numpy.random.randint(2))]
    operators_b = [(numpy.random.randint(n_qubits),
                    numpy.random.randint(2))]
    for _ in range(term_length):

        # Make sure the operator is not trivially zero.
        operator_a = (numpy.random.randint(n_qubits),
                      numpy.random.randint(2))
        while operator_a == operators_a[-1]:
            operator_a = (numpy.random.randint(n_qubits),
                          numpy.random.randint(2))
        operators_a += [operator_a]

        # Do the same for the other operator.
        operator_b = (numpy.random.randint(n_qubits),
                      numpy.random.randint(2))
        while operator_b == operators_b[-1]:
            operator_b = (numpy.random.randint(n_qubits),
                          numpy.random.randint(2))
        operators_b += [operator_b]

    # Initialize FermionTerms and then sum them together.
    fermion_term_a = FermionOperator(tuple(operators_a),
                                     float(numpy.random.randn()))
    fermion_term_b = FermionOperator(tuple(operators_b),
                                     float(numpy.random.randn()))
    fermion_operator = fermion_term_a + fermion_term_b

    # Exponentiate.
    start_time = time.time()
    fermion_operator **= power
    runtime_math = time.time() - start_time

    # Normal order.
    start_time = time.time()
    normal_ordered(fermion_operator)
    runtime_normal_order = time.time() - start_time

    # Return.
    return runtime_math, runtime_normal_order
Beispiel #2
0
    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)
Beispiel #3
0
    def test_integration_jellium_hamiltonian_with_negation(self):
        hamiltonian = normal_ordered(
            jellium_model(Grid(2, 3, 1.), plane_wave=False))

        part_a = FermionOperator.zero()
        part_b = FermionOperator.zero()

        add_to_a_or_b = 0  # add to a if 0; add to b if 1
        for term, coeff in hamiltonian.terms.items():
            # Partition terms in the Hamiltonian into part_a or part_b
            if add_to_a_or_b:
                part_a += FermionOperator(term, coeff)
            else:
                part_b += FermionOperator(term, coeff)
            add_to_a_or_b ^= 1

        reference = normal_ordered(commutator(part_a, part_b))
        result = commutator_ordered_diagonal_coulomb_with_two_body_operator(
            part_a, part_b)

        self.assertTrue(result.isclose(reference))

        negative = commutator_ordered_diagonal_coulomb_with_two_body_operator(
            part_b, part_a)
        result += negative

        self.assertTrue(result.isclose(FermionOperator.zero()))
 def test_majorana_form(self):
     """Test getting the Majorana form."""
     majorana_matrix, majorana_constant = self.quad_ham_npc.majorana_form()
     # Convert the Majorana form to a FermionOperator
     majorana_op = FermionOperator((), majorana_constant)
     normalization = 1. / numpy.sqrt(2.)
     for i in range(2 * self.n_qubits):
         if i < self.n_qubits:
             left_op = majorana_operator((i, 0), normalization)
         else:
             left_op = majorana_operator((i - self.n_qubits, 1),
                                         normalization)
         for j in range(2 * self.n_qubits):
             if j < self.n_qubits:
                 right_op = majorana_operator(
                     (j, 0), majorana_matrix[i, j] * normalization)
             else:
                 right_op = majorana_operator(
                     (j - self.n_qubits, 1),
                     majorana_matrix[i, j] * normalization)
             majorana_op += .5j * left_op * right_op
     # Get FermionOperator for original Hamiltonian
     fermion_operator = normal_ordered(
         get_fermion_operator(self.quad_ham_npc))
     self.assertTrue(normal_ordered(majorana_op) == fermion_operator)
Beispiel #5
0
    def test_commutes_number_operators(self):
        com = commutator(FermionOperator('4^ 3^ 4 3'), FermionOperator('2^ 2'))
        com = normal_ordered(com)
        self.assertEqual(com, FermionOperator.zero())

        com = commutator(BosonOperator('4^ 3^ 4 3'), BosonOperator('2^ 2'))
        com = normal_ordered(com)
        self.assertTrue(com == BosonOperator.zero())
Beispiel #6
0
    def test_commutator_hopping_operators(self):
        com = commutator(3 * FermionOperator('1^ 2'), FermionOperator('2^ 3'))
        com = normal_ordered(com)
        self.assertEqual(com, FermionOperator('1^ 3', 3))

        com = commutator(3 * BosonOperator('1^ 2'), BosonOperator('2^ 3'))
        com = normal_ordered(com)
        self.assertTrue(com == BosonOperator('1^ 3', 3))
 def test_ccr_onsite(self):
     c1 = FermionOperator(((1, 1), ))
     a1 = hermitian_conjugated(c1)
     self.assertTrue(
         normal_ordered(c1 * a1) == FermionOperator(()) -
         normal_ordered(a1 * c1))
     self.assertTrue(
         jordan_wigner(c1 * a1) == QubitOperator(()) -
         jordan_wigner(a1 * c1))
    def test_jordan_wigner_twobody_interaction_op_allunique(self):
        test_op = FermionOperator('1^ 2^ 3 4')
        test_op += hermitian_conjugated(test_op)

        retransformed_test_op = reverse_jordan_wigner(
            jordan_wigner(get_interaction_operator(test_op)))

        self.assertTrue(
            normal_ordered(retransformed_test_op) == normal_ordered(test_op))
 def test_inverse_fourier_transform_2d(self):
     grid = Grid(dimensions=2, scale=1.5, length=3)
     spinless = True
     geometry = [('H', (0, 0)), ('H', (0.5, 0.8))]
     h_plane_wave = plane_wave_hamiltonian(grid, geometry, spinless, True)
     h_dual_basis = plane_wave_hamiltonian(grid, geometry, spinless, False)
     h_dual_basis_t = inverse_fourier_transform(h_dual_basis, grid,
                                                spinless)
     self.assertEqual(normal_ordered(h_dual_basis_t),
                      normal_ordered(h_plane_wave))
Beispiel #10
0
    def test_uccsd_singlet_builds(self):
        """Test specific builds of the UCCSD singlet operator"""
        # Build 1
        n_orbitals = 4
        n_electrons = 2
        n_params = uccsd_singlet_paramsize(n_orbitals, n_electrons)
        self.assertEqual(n_params, 2)

        initial_amplitudes = [1., 2.]

        generator = uccsd_singlet_generator(initial_amplitudes, n_orbitals,
                                            n_electrons)

        test_generator = (FermionOperator("2^ 0", 1.) +
                          FermionOperator("0^ 2", -1.) +
                          FermionOperator("3^ 1", 1.) +
                          FermionOperator("1^ 3", -1.) +
                          FermionOperator("2^ 0 3^ 1", 4.) +
                          FermionOperator("1^ 3 0^ 2", -4.))

        self.assertEqual(normal_ordered(test_generator),
                         normal_ordered(generator))

        # Build 2
        n_orbitals = 6
        n_electrons = 2

        n_params = uccsd_singlet_paramsize(n_orbitals, n_electrons)
        self.assertEqual(n_params, 5)

        initial_amplitudes = numpy.arange(1, n_params + 1, dtype=float)
        generator = uccsd_singlet_generator(initial_amplitudes, n_orbitals,
                                            n_electrons)

        test_generator = (
            FermionOperator("2^ 0", 1.) + FermionOperator("0^ 2", -1) +
            FermionOperator("3^ 1", 1.) + FermionOperator("1^ 3", -1.) +
            FermionOperator("4^ 0", 2.) + FermionOperator("0^ 4", -2) +
            FermionOperator("5^ 1", 2.) + FermionOperator("1^ 5", -2.) +
            FermionOperator("2^ 0 3^ 1", 6.) +
            FermionOperator("1^ 3 0^ 2", -6.) +
            FermionOperator("4^ 0 5^ 1", 8.) +
            FermionOperator("1^ 5 0^ 4", -8.) +
            FermionOperator("2^ 0 5^ 1", 5.) +
            FermionOperator("1^ 5 0^ 2", -5.) +
            FermionOperator("4^ 0 3^ 1", 5.) +
            FermionOperator("1^ 3 0^ 4", -5.) +
            FermionOperator("2^ 0 4^ 0", 5.) +
            FermionOperator("0^ 4 0^ 2", -5.) +
            FermionOperator("3^ 1 5^ 1", 5.) +
            FermionOperator("1^ 5 1^ 3", -5.))

        self.assertEqual(normal_ordered(test_generator),
                         normal_ordered(generator))
Beispiel #11
0
    def test_commutes_no_intersection(self):
        com = commutator(FermionOperator('2^ 3'), FermionOperator('4^ 5^ 3'))
        com = normal_ordered(com)
        self.assertEqual(com, FermionOperator.zero())

        com = commutator(BosonOperator('2^ 3'), BosonOperator('4^ 5^ 3'))
        com = normal_ordered(com)
        self.assertTrue(com == BosonOperator.zero())

        com = commutator(QuadOperator('q2 p3'), QuadOperator('q4 q5 p3'))
        com = normal_ordered(com)
        self.assertTrue(com == QuadOperator.zero())
    def test_jordan_wigner_interaction_op_with_zero_term(self):
        test_op = FermionOperator('1^ 2^ 3 4')
        test_op += hermitian_conjugated(test_op)

        interaction_op = get_interaction_operator(test_op)
        interaction_op.constant = 0.0

        retransformed_test_op = reverse_jordan_wigner(
            jordan_wigner(interaction_op))

        self.assertEqual(normal_ordered(retransformed_test_op),
                         normal_ordered(test_op))
    def test_yy(self):
        yy = QubitOperator(((2, 'Y'), (3, 'Y')), 2.)
        transmed_yy = reverse_jordan_wigner(yy)
        retransmed_yy = jordan_wigner(transmed_yy)

        expected1 = -(FermionOperator(((2, 1), ), 2.) + FermionOperator(
            ((2, 0), ), 2.))
        expected2 = (FermionOperator(((3, 1), )) - FermionOperator(((3, 0), )))
        expected = expected1 * expected2

        self.assertTrue(yy == retransmed_yy)
        self.assertTrue(
            normal_ordered(transmed_yy) == normal_ordered(expected))
    def test_xy(self):
        xy = QubitOperator(((4, 'X'), (5, 'Y')), -2.j)
        transmed_xy = reverse_jordan_wigner(xy)
        retransmed_xy = jordan_wigner(transmed_xy)

        expected1 = -2j * (FermionOperator(((4, 1), ), 1j) - FermionOperator(
            ((4, 0), ), 1j))
        expected2 = (FermionOperator(((5, 1), )) - FermionOperator(((5, 0), )))
        expected = expected1 * expected2

        self.assertTrue(xy == retransmed_xy)
        self.assertTrue(
            normal_ordered(transmed_xy) == normal_ordered(expected))
Beispiel #15
0
    def test_integration_random_diagonal_coulomb_hamiltonian(self):
        hamiltonian1 = normal_ordered(
            get_fermion_operator(
                random_diagonal_coulomb_hamiltonian(n_qubits=7)))
        hamiltonian2 = normal_ordered(
            get_fermion_operator(
                random_diagonal_coulomb_hamiltonian(n_qubits=7)))

        reference = normal_ordered(commutator(hamiltonian1, hamiltonian2))
        result = commutator_ordered_diagonal_coulomb_with_two_body_operator(
            hamiltonian1, hamiltonian2)

        self.assertTrue(result.isclose(reference))
 def test_inverse_fourier_transform_1d(self):
     grid = Grid(dimensions=1, scale=1.5, length=4)
     spinless_set = [True, False]
     geometry = [('H', (0, )), ('H', (0.5, ))]
     for spinless in spinless_set:
         h_plane_wave = plane_wave_hamiltonian(grid, geometry, spinless,
                                               True)
         h_dual_basis = plane_wave_hamiltonian(grid, geometry, spinless,
                                               False)
         h_dual_basis_t = inverse_fourier_transform(h_dual_basis, grid,
                                                    spinless)
         self.assertEqual(normal_ordered(h_dual_basis_t),
                          normal_ordered(h_plane_wave))
    def test_yx(self):
        yx = QubitOperator(((0, 'Y'), (1, 'X')), -0.5)
        transmed_yx = reverse_jordan_wigner(yx)
        retransmed_yx = jordan_wigner(transmed_yx)

        expected1 = 1j * (FermionOperator(((0, 1), )) + FermionOperator(
            ((0, 0), )))
        expected2 = -0.5 * (FermionOperator(((1, 1), )) + FermionOperator(
            ((1, 0), )))
        expected = expected1 * expected2

        self.assertTrue(yx == retransmed_yx)
        self.assertTrue(
            normal_ordered(transmed_yx) == normal_ordered(expected))
    def test_xx(self):
        xx = QubitOperator(((3, 'X'), (4, 'X')), 2.)
        transmed_xx = reverse_jordan_wigner(xx)
        retransmed_xx = jordan_wigner(transmed_xx)

        expected1 = (FermionOperator(((3, 1), ), 2.) - FermionOperator(
            ((3, 0), ), 2.))
        expected2 = (FermionOperator(((4, 1), ), 1.) + FermionOperator(
            ((4, 0), ), 1.))
        expected = expected1 * expected2

        self.assertTrue(xx == retransmed_xx)
        self.assertTrue(
            normal_ordered(transmed_xx) == normal_ordered(expected))
Beispiel #19
0
def test_erpa_eom_ham_lih():
    filename = os.path.join(DATA_DIRECTORY, "H1-Li1_sto-3g_singlet_1.45.hdf5")
    molecule = MolecularData(filename=filename)
    reduced_ham = make_reduced_hamiltonian(
        molecule.get_molecular_hamiltonian(), molecule.n_electrons)
    rha_fermion = get_fermion_operator(reduced_ham)
    permuted_hijkl = np.einsum('ijlk', reduced_ham.two_body_tensor)
    opdm = np.diag([1] * molecule.n_electrons + [0] *
                   (molecule.n_qubits - molecule.n_electrons))
    tpdm = 2 * wedge(opdm, opdm, (1, 1), (1, 1))
    rdms = InteractionRDM(opdm, tpdm)
    dim = 3  # so we don't do the full basis.  This would make the test long
    full_basis = {}  # erpa basis.  A, B basis in RPA language
    cnt = 0
    # start from 1 to make test shorter
    for p, q in product(range(1, dim), repeat=2):
        if p < q:
            full_basis[(p, q)] = cnt
            full_basis[(q, p)] = cnt + dim * (dim - 1) // 2
            cnt += 1
    for rkey in full_basis.keys():
        p, q = rkey
        for ckey in full_basis.keys():
            r, s = ckey
            for sigma, tau in product([0, 1], repeat=2):
                test = erpa_eom_hamiltonian(permuted_hijkl, tpdm,
                                            2 * q + sigma, 2 * p + sigma,
                                            2 * r + tau, 2 * s + tau).real
                qp_op = FermionOperator(
                    ((2 * q + sigma, 1), (2 * p + sigma, 0)))
                rs_op = FermionOperator(((2 * r + tau, 1), (2 * s + tau, 0)))
                erpa_op = normal_ordered(
                    commutator(qp_op, commutator(rha_fermion, rs_op)))
                true = rdms.expectation(get_interaction_operator(erpa_op))
                assert np.isclose(true, test)
Beispiel #20
0
    def test_commutator(self):
        operator_a = (
            FermionOperator('0^ 0', 0.3) + FermionOperator('1^ 1', 0.1j) +
            FermionOperator('1^ 0^ 1 0', -0.2) + FermionOperator('1^ 3') +
            FermionOperator('3^ 0') + FermionOperator('3^ 2', 0.017) -
            FermionOperator('2^ 3', 1.99) + FermionOperator('3^ 1^ 3 1', .09) +
            FermionOperator('2^ 0^ 2 0', .126j) +
            FermionOperator('4^ 2^ 4 2') + FermionOperator('3^ 0^ 3 0'))

        operator_b = (
            FermionOperator('3^ 1', 0.7) + FermionOperator('1^ 3', -9.) +
            FermionOperator('1^ 0^ 3 0', 0.1) -
            FermionOperator('3^ 0^ 1 0', 0.11) + FermionOperator('3^ 2^ 3 2') +
            FermionOperator('3^ 1^ 3 1', -1.37) +
            FermionOperator('4^ 2^ 4 2') + FermionOperator('4^ 1^ 4 1') +
            FermionOperator('1^ 0^ 4 0', 16.7) +
            FermionOperator('1^ 0^ 4 3', 1.67) +
            FermionOperator('4^ 3^ 5 2', 1.789j) +
            FermionOperator('6^ 5^ 4 1', -11.789j))

        reference = normal_ordered(commutator(operator_a, operator_b))
        result = commutator_ordered_diagonal_coulomb_with_two_body_operator(
            operator_a, operator_b)

        diff = result - reference
        self.assertTrue(diff.isclose(FermionOperator.zero()))
Beispiel #21
0
def ordered_low_depth_terms_no_info(hamiltonian):
    """Give terms from Hamiltonian in dictionary output order.

    Args:
        hamiltonian (FermionOperator): The Hamiltonian.

    Returns:
        A list of terms from the Hamiltonian in simulated order.

    Notes:
        Assumes the Hamiltonian is in the form discussed in Kivlichan
        et al., "Quantum Simulation of Electronic Structure with Linear
        Depth and Connectivity", arxiv:1711.04789. This constrains the
        Hamiltonian to have only hopping terms (i^ j + j^ i) and potential
        terms which are products of at most two number operators (n_i or
        n_i n_j).
    """
    count_qubits(hamiltonian)
    hamiltonian = normal_ordered(hamiltonian)
    terms = []

    for operators, coefficient in hamiltonian.terms.items():
        terms += [FermionOperator(operators, coefficient)]

    return terms
Beispiel #22
0
    def setUp(self):
        geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))]
        basis = 'sto-3g'
        multiplicity = 1
        filename = os.path.join(DATA_DIRECTORY, 'H2_sto-3g_singlet_0.7414')
        self.molecule = MolecularData(geometry,
                                      basis,
                                      multiplicity,
                                      filename=filename)
        self.molecule.load()

        # Get molecular Hamiltonian.
        self.molecular_hamiltonian = self.molecule.get_molecular_hamiltonian()

        # Get FCI RDM.
        self.fci_rdm = self.molecule.get_molecular_rdm(use_fci=1)
        # Get explicit coefficients.
        self.nuclear_repulsion = self.molecular_hamiltonian.constant
        self.one_body = self.molecular_hamiltonian.one_body_tensor
        self.two_body = self.molecular_hamiltonian.two_body_tensor

        # Get fermion Hamiltonian.
        self.fermion_hamiltonian = normal_ordered(
            get_fermion_operator(self.molecular_hamiltonian))

        # Get qubit Hamiltonian.
        self.qubit_hamiltonian = jordan_wigner(self.fermion_hamiltonian)

        # Get the sparse matrix.
        self.hamiltonian_matrix = get_sparse_operator(
            self.molecular_hamiltonian)
Beispiel #23
0
    def test_molecular_operator_consistency(self):

        # Initialize H2 InteractionOperator.
        n_qubits = 4
        filename = os.path.join(THIS_DIRECTORY, 'data',
                                'H2_sto-3g_singlet_0.7414')
        molecule = MolecularData(filename=filename)
        molecule_interaction = molecule.get_molecular_hamiltonian()
        molecule_operator = get_fermion_operator(molecule_interaction)

        constant = molecule_interaction.constant
        one_body_coefficients = molecule_interaction.one_body_tensor
        two_body_coefficients = molecule_interaction.two_body_tensor

        # Perform decomposition.
        eigenvalues, one_body_squares, one_body_corrections, trunc_error = (
            low_rank_two_body_decomposition(two_body_coefficients))
        self.assertAlmostEqual(trunc_error, 0.)

        # Build back operator constant and one-body components.
        decomposed_operator = FermionOperator((), constant)
        for p, q in itertools.product(range(n_qubits), repeat=2):
            term = ((p, 1), (q, 0))
            coefficient = (one_body_coefficients[p, q] +
                           one_body_corrections[p, q])
            decomposed_operator += FermionOperator(term, coefficient)

        # Build back two-body component.
        for l in range(one_body_squares.shape[0]):
            one_body_operator = FermionOperator()
            for p, q in itertools.product(range(n_qubits), repeat=2):
                term = ((p, 1), (q, 0))
                coefficient = one_body_squares[l, p, q]
                if abs(eigenvalues[l]) > 1e-6:
                    self.assertTrue(is_hermitian(one_body_squares[l]))
                one_body_operator += FermionOperator(term, coefficient)
            decomposed_operator += eigenvalues[l] * (one_body_operator**2)

        # Test for consistency.
        difference = normal_ordered(decomposed_operator - molecule_operator)
        self.assertAlmostEqual(0., difference.induced_norm())

        # Decompose with slightly negative operator that must use eigen
        molecule = MolecularData(filename=filename)
        molecule.two_body_integrals[0, 0, 0, 0] -= 1

        eigenvalues, one_body_squares, one_body_corrections, trunc_error = (
            low_rank_two_body_decomposition(two_body_coefficients))
        self.assertAlmostEqual(trunc_error, 0.)

        # Check for property errors
        with self.assertRaises(TypeError):
            eigenvalues, one_body_squares, _, trunc_error = (
                low_rank_two_body_decomposition(two_body_coefficients + 0.01j,
                                                truncation_threshold=1.,
                                                final_rank=1))
Beispiel #24
0
    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 benchmark_commutator_diagonal_coulomb_operators_2D_spinless_jellium(
        side_length):
    """Test speed of computing commutators using specialized functions.

    Args:
        side_length: The side length of the 2D jellium grid. There are
            side_length ** 2 qubits, and O(side_length ** 4) terms in the
            Hamiltonian.

    Returns:
        runtime_commutator: The time it takes to compute a commutator, after
            partitioning the terms and normal ordering, using the regular
            commutator function.
        runtime_diagonal_commutator: The time it takes to compute the same
            commutator using methods restricted to diagonal Coulomb operators.
    """
    hamiltonian = normal_ordered(
        jellium_model(Grid(2, side_length, 1.), plane_wave=False))

    part_a = FermionOperator.zero()
    part_b = FermionOperator.zero()
    add_to_a_or_b = 0  # add to a if 0; add to b if 1
    for term, coeff in hamiltonian.terms.items():
        # Partition terms in the Hamiltonian into part_a or part_b
        if add_to_a_or_b:
            part_a += FermionOperator(term, coeff)
        else:
            part_b += FermionOperator(term, coeff)
        add_to_a_or_b ^= 1

    start = time.time()
    _ = normal_ordered(commutator(part_a, part_b))
    end = time.time()
    runtime_commutator = end - start

    start = time.time()
    _ = commutator_ordered_diagonal_coulomb_with_two_body_operator(
        part_a, part_b)
    end = time.time()
    runtime_diagonal_commutator = end - start

    return runtime_commutator, runtime_diagonal_commutator
    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.
        """
        # Importing here instead of head of file to prevent circulars
        from openfermion.transforms.opconversions import (
            reverse_jordan_wigner, 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
Beispiel #27
0
    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)
Beispiel #28
0
    def test_uccsd_singlet_symmetries(self):
        """Test that the singlet generator has the correct symmetries."""
        test_orbitals = 8
        test_electrons = 4

        packed_amplitude_size = uccsd_singlet_paramsize(
            test_orbitals, test_electrons)
        packed_amplitudes = randn(int(packed_amplitude_size))
        generator = uccsd_singlet_generator(packed_amplitudes, test_orbitals,
                                            test_electrons)

        # Construct symmetry operators
        sz = sz_operator(test_orbitals)
        s_squared = s_squared_operator(test_orbitals)

        # Check the symmetries
        comm_sz = normal_ordered(commutator(generator, sz))
        comm_s_squared = normal_ordered(commutator(generator, s_squared))
        zero = FermionOperator()

        self.assertEqual(comm_sz, zero)
        self.assertEqual(comm_s_squared, zero)
Beispiel #29
0
    def test_split_operator_error_operator_VT_order_against_definition(self):
        hamiltonian = (normal_ordered(fermi_hubbard(3, 3, 1., 4.0)) -
                       2.3 * FermionOperator.identity())
        potential_terms, kinetic_terms = (
            diagonal_coulomb_potential_and_kinetic_terms_as_arrays(hamiltonian)
        )
        potential = sum(potential_terms, FermionOperator.zero())
        kinetic = sum(kinetic_terms, FermionOperator.zero())

        error_operator = (
            split_operator_trotter_error_operator_diagonal_two_body(
                hamiltonian, order='V+T'))

        # V-then-T ordered double commutators: [V, [T, V]] + [T, [T, V]] / 2
        inner_commutator = normal_ordered(commutator(kinetic, potential))
        error_operator_definition = normal_ordered(
            commutator(potential, inner_commutator))
        error_operator_definition += normal_ordered(
            commutator(kinetic, inner_commutator)) / 2.0
        error_operator_definition /= 12.0

        self.assertEqual(error_operator, error_operator_definition)
    def test_fourier_transform(self):
        for length in [2, 3]:
            grid = Grid(dimensions=1, scale=1.5, length=length)
            spinless_set = [True, False]
            geometry = [('H', (0.1, )), ('H', (0.5, ))]
            for spinless in spinless_set:
                h_plane_wave = plane_wave_hamiltonian(grid, geometry, spinless,
                                                      True)
                h_dual_basis = plane_wave_hamiltonian(grid, geometry, spinless,
                                                      False)
                h_plane_wave_t = fourier_transform(h_plane_wave, grid,
                                                   spinless)

                self.assertEqual(normal_ordered(h_plane_wave_t),
                                 normal_ordered(h_dual_basis))

                # Verify that all 3 are Hermitian
                plane_wave_operator = get_sparse_operator(h_plane_wave)
                dual_operator = get_sparse_operator(h_dual_basis)
                plane_wave_t_operator = get_sparse_operator(h_plane_wave_t)
                self.assertTrue(is_hermitian(plane_wave_operator))
                self.assertTrue(is_hermitian(dual_operator))
                self.assertTrue(is_hermitian(plane_wave_t_operator))