1# Licensed under the Apache License, Version 2.0 (the "License"); 2# you may not use this file except in compliance with the License. 3# You may obtain a copy of the License at 4# 5# http://www.apache.org/licenses/LICENSE-2.0 6# 7# Unless required by applicable law or agreed to in writing, software 8# distributed under the License is distributed on an "AS IS" BASIS, 9# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10# See the License for the specific language governing permissions and 11# limitations under the License. 12"""Tests for commutator_diagonal_coulomb_operator.py""" 13 14import unittest 15import warnings 16 17from openfermion.ops.operators import FermionOperator 18from openfermion.transforms.opconversions import get_fermion_operator 19from openfermion.hamiltonians import jellium_model 20from openfermion.utils import commutator, Grid 21from openfermion.transforms.opconversions import normal_ordered 22from openfermion.transforms.opconversions\ 23 .commutator_diagonal_coulomb_operator import ( 24 commutator_ordered_diagonal_coulomb_with_two_body_operator) 25from openfermion.testing.testing_utils import ( 26 random_diagonal_coulomb_hamiltonian) 27 28 29class DiagonalHamiltonianCommutatorTest(unittest.TestCase): 30 31 def test_commutator(self): 32 operator_a = ( 33 FermionOperator('0^ 0', 0.3) + FermionOperator('1^ 1', 0.1j) + 34 FermionOperator('1^ 0^ 1 0', -0.2) + FermionOperator('1^ 3') + 35 FermionOperator('3^ 0') + FermionOperator('3^ 2', 0.017) - 36 FermionOperator('2^ 3', 1.99) + FermionOperator('3^ 1^ 3 1', .09) + 37 FermionOperator('2^ 0^ 2 0', .126j) + FermionOperator('4^ 2^ 4 2') + 38 FermionOperator('3^ 0^ 3 0')) 39 40 operator_b = ( 41 FermionOperator('3^ 1', 0.7) + FermionOperator('1^ 3', -9.) + 42 FermionOperator('1^ 0^ 3 0', 0.1) - 43 FermionOperator('3^ 0^ 1 0', 0.11) + FermionOperator('3^ 2^ 3 2') + 44 FermionOperator('3^ 1^ 3 1', -1.37) + FermionOperator('4^ 2^ 4 2') + 45 FermionOperator('4^ 1^ 4 1') + FermionOperator('1^ 0^ 4 0', 16.7) + 46 FermionOperator('1^ 0^ 4 3', 1.67) + 47 FermionOperator('4^ 3^ 5 2', 1.789j) + 48 FermionOperator('6^ 5^ 4 1', -11.789j)) 49 50 reference = normal_ordered(commutator(operator_a, operator_b)) 51 result = commutator_ordered_diagonal_coulomb_with_two_body_operator( 52 operator_a, operator_b) 53 54 diff = result - reference 55 self.assertTrue(diff.isclose(FermionOperator.zero())) 56 57 def test_nonstandard_second_arg(self): 58 operator_a = (FermionOperator('0^ 0', 0.3) + 59 FermionOperator('1^ 1', 0.1j) + 60 FermionOperator('2^ 0^ 2 0', -0.2) + 61 FermionOperator('2^ 1^ 2 1', -0.2j) + 62 FermionOperator('1^ 3') + FermionOperator('3^ 0') + 63 FermionOperator('4^ 4', -1.4j)) 64 65 operator_b = (FermionOperator('4^ 1^ 3 0', 0.1) - 66 FermionOperator('3^ 0^ 1 0', 0.11)) 67 68 reference = (FermionOperator('1^ 0^ 1 0', -0.11) + 69 FermionOperator('3^ 0^ 1 0', 0.011j) + 70 FermionOperator('3^ 0^ 3 0', 0.11) + 71 FermionOperator('3^ 2^ 0^ 2 1 0', -0.022j) + 72 FermionOperator('4^ 1^ 3 0', -0.03 - 0.13j) + 73 FermionOperator('4^ 2^ 1^ 3 2 0', -0.02 + 0.02j)) 74 75 res = commutator_ordered_diagonal_coulomb_with_two_body_operator( 76 operator_a, operator_b) 77 78 self.assertTrue(res.isclose(reference)) 79 80 def test_add_to_existing_result(self): 81 prior_terms = FermionOperator('0^ 1') 82 operator_a = FermionOperator('2^ 1') 83 operator_b = FermionOperator('0^ 2') 84 85 commutator_ordered_diagonal_coulomb_with_two_body_operator( 86 operator_a, operator_b, prior_terms=prior_terms) 87 88 self.assertTrue(prior_terms.isclose(FermionOperator.zero())) 89 90 def test_integration_jellium_hamiltonian_with_negation(self): 91 hamiltonian = normal_ordered( 92 jellium_model(Grid(2, 3, 1.), plane_wave=False)) 93 94 part_a = FermionOperator.zero() 95 part_b = FermionOperator.zero() 96 97 add_to_a_or_b = 0 # add to a if 0; add to b if 1 98 for term, coeff in hamiltonian.terms.items(): 99 # Partition terms in the Hamiltonian into part_a or part_b 100 if add_to_a_or_b: 101 part_a += FermionOperator(term, coeff) 102 else: 103 part_b += FermionOperator(term, coeff) 104 add_to_a_or_b ^= 1 105 106 reference = normal_ordered(commutator(part_a, part_b)) 107 result = commutator_ordered_diagonal_coulomb_with_two_body_operator( 108 part_a, part_b) 109 110 self.assertTrue(result.isclose(reference)) 111 112 negative = commutator_ordered_diagonal_coulomb_with_two_body_operator( 113 part_b, part_a) 114 result += negative 115 116 self.assertTrue(result.isclose(FermionOperator.zero())) 117 118 def test_no_warning_on_nonstandard_input_second_arg(self): 119 with warnings.catch_warnings(record=True) as w: 120 operator_a = FermionOperator('3^ 2^ 3 2') 121 operator_b = FermionOperator('4^ 3^ 4 1') 122 123 reference = FermionOperator('4^ 3^ 2^ 4 2 1') 124 result = ( 125 commutator_ordered_diagonal_coulomb_with_two_body_operator( 126 operator_a, operator_b)) 127 128 self.assertFalse(w) 129 130 # Result should still be correct even though we hit the warning. 131 self.assertTrue(result.isclose(reference)) 132 133 def test_warning_on_bad_input_first_arg(self): 134 with warnings.catch_warnings(record=True) as w: 135 operator_a = FermionOperator('4^ 3^ 2 1') 136 operator_b = FermionOperator('3^ 2^ 3 2') 137 138 reference = normal_ordered(commutator(operator_a, operator_b)) 139 result = ( 140 commutator_ordered_diagonal_coulomb_with_two_body_operator( 141 operator_a, operator_b)) 142 143 self.assertTrue(len(w) == 1) 144 self.assertIn('Defaulted to standard commutator evaluation', 145 str(w[-1].message)) 146 147 # Result should still be correct in this case. 148 diff = result - reference 149 self.assertTrue(diff.isclose(FermionOperator.zero())) 150 151 def test_integration_random_diagonal_coulomb_hamiltonian(self): 152 hamiltonian1 = normal_ordered( 153 get_fermion_operator( 154 random_diagonal_coulomb_hamiltonian(n_qubits=7))) 155 hamiltonian2 = normal_ordered( 156 get_fermion_operator( 157 random_diagonal_coulomb_hamiltonian(n_qubits=7))) 158 159 reference = normal_ordered(commutator(hamiltonian1, hamiltonian2)) 160 result = commutator_ordered_diagonal_coulomb_with_two_body_operator( 161 hamiltonian1, hamiltonian2) 162 163 self.assertTrue(result.isclose(reference)) 164