def test_identity(self): n_qubits = 5 transmed_i = reverse_jordan_wigner(self.identity, n_qubits) expected_i = FermionOperator(()) self.assertTrue(transmed_i == expected_i) retransmed_i = jordan_wigner(transmed_i) self.assertTrue(self.identity == retransmed_i)
def test_jw_convention(self): """Test that the Jordan-Wigner convention places the Z-string on lower indices.""" qubit_op = QubitOperator('Z0 X1') transformed_op = reverse_jordan_wigner(qubit_op) expected_op = FermionOperator('1^') expected_op += FermionOperator('1') self.assertTrue(transformed_op == expected_op)
def test_get_interaction_operator_identity(self): interaction_operator = InteractionOperator(-2j, self.one_body, self.two_body) qubit_operator = jordan_wigner(interaction_operator) self.assertTrue(qubit_operator == -2j * QubitOperator(())) self.assertEqual( interaction_operator, get_interaction_operator(reverse_jordan_wigner(qubit_operator), self.n_qubits))
def test_zero(self): n_qubits = 5 transmed_i = reverse_jordan_wigner(QubitOperator(), n_qubits) expected_i = FermionOperator() self.assertTrue(transmed_i == expected_i) retransmed_i = jordan_wigner(transmed_i) expected_i = QubitOperator() self.assertTrue(expected_i == retransmed_i)
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_z(self): pauli_z = QubitOperator(((2, 'Z'), )) transmed_z = reverse_jordan_wigner(pauli_z) expected = (FermionOperator(()) + FermionOperator( ((2, 1), (2, 0)), -2.)) self.assertTrue(transmed_z == expected) retransmed_z = jordan_wigner(transmed_z) self.assertTrue(pauli_z == retransmed_z)
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 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
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))
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))
def test_reverse_jordan_wigner(self): fermion_hamiltonian = reverse_jordan_wigner(self.qubit_hamiltonian) fermion_hamiltonian = normal_ordered(fermion_hamiltonian) self.assertTrue(self.fermion_hamiltonian == fermion_hamiltonian)
def test_term(self): transmed_term = reverse_jordan_wigner(self.term) retransmed_term = jordan_wigner(transmed_term) self.assertTrue(self.term == retransmed_term)
def test_yzxz(self): yzxz = QubitOperator(((0, 'Y'), (1, 'Z'), (2, 'X'), (3, 'Z'))) transmed_yzxz = reverse_jordan_wigner(yzxz) retransmed_yzxz = jordan_wigner(transmed_yzxz) self.assertTrue(yzxz == retransmed_yzxz)
def test_reverse_jordan_wigner(self): transmed_operator = reverse_jordan_wigner(self.qubit_operator) retransmed_operator = jordan_wigner(transmed_operator) self.assertTrue(self.qubit_operator == retransmed_operator)
def test_reverse_jw_linearity(self): term1 = QubitOperator(((0, 'X'), (1, 'Y')), -0.5) term2 = QubitOperator(((0, 'Y'), (1, 'X'), (2, 'Y'), (3, 'Y')), -1j) op12 = reverse_jordan_wigner(term1) - reverse_jordan_wigner(term2) self.assertTrue(op12 == reverse_jordan_wigner(term1 - term2))
def test_bad_type(self): with self.assertRaises(TypeError): reverse_jordan_wigner(3)
def test_y(self): pauli_y = QubitOperator(((2, 'Y'), )) transmed_y = reverse_jordan_wigner(pauli_y) retransmed_y = jordan_wigner(transmed_y) self.assertTrue(pauli_y == retransmed_y)
def test_x(self): pauli_x = QubitOperator(((2, 'X'), )) transmed_x = reverse_jordan_wigner(pauli_x) retransmed_x = jordan_wigner(transmed_x) self.assertTrue(pauli_x == retransmed_x)
def test_identity_jwterm(self): self.assertTrue( FermionOperator(()) == reverse_jordan_wigner(QubitOperator(())))
def test_all(self): # Test reverse Jordan-Wigner. fermion_hamiltonian = reverse_jordan_wigner(self.qubit_hamiltonian) fermion_hamiltonian = normal_ordered(fermion_hamiltonian) self.assertTrue(self.fermion_hamiltonian == fermion_hamiltonian) # Test mapping to interaction operator. fermion_hamiltonian = get_fermion_operator(self.molecular_hamiltonian) fermion_hamiltonian = normal_ordered(fermion_hamiltonian) self.assertTrue(self.fermion_hamiltonian == fermion_hamiltonian) # Test RDM energy. fci_rdm_energy = self.nuclear_repulsion fci_rdm_energy += numpy.sum(self.fci_rdm.one_body_tensor * self.one_body) fci_rdm_energy += numpy.sum(self.fci_rdm.two_body_tensor * self.two_body) self.assertAlmostEqual(fci_rdm_energy, self.molecule.fci_energy) # Confirm expectation on qubit Hamiltonian using reverse JW matches. qubit_rdm = self.fci_rdm.get_qubit_expectations(self.qubit_hamiltonian) qubit_energy = 0.0 for term, coefficient in qubit_rdm.terms.items(): qubit_energy += coefficient * self.qubit_hamiltonian.terms[term] self.assertAlmostEqual(qubit_energy, self.molecule.fci_energy) # Confirm fermionic RDMs can be built from measured qubit RDMs. new_fermi_rdm = get_interaction_rdm(qubit_rdm) new_fermi_rdm.expectation(self.molecular_hamiltonian) self.assertAlmostEqual(fci_rdm_energy, self.molecule.fci_energy) # Test sparse matrices. energy, wavefunction = get_ground_state(self.hamiltonian_matrix) self.assertAlmostEqual(energy, self.molecule.fci_energy) expected_energy = expectation(self.hamiltonian_matrix, wavefunction) self.assertAlmostEqual(expected_energy, energy) # Make sure you can reproduce Hartree-Fock energy. hf_state = jw_hartree_fock_state(self.molecule.n_electrons, count_qubits(self.qubit_hamiltonian)) hf_density = get_density_matrix([hf_state], [1.]) expected_hf_density_energy = expectation(self.hamiltonian_matrix, hf_density) expected_hf_energy = expectation(self.hamiltonian_matrix, hf_state) self.assertAlmostEqual(expected_hf_energy, self.molecule.hf_energy) self.assertAlmostEqual(expected_hf_density_energy, self.molecule.hf_energy) # Check that frozen core result matches frozen core FCI from psi4. # Recore frozen core result from external calculation. self.frozen_core_fci_energy = -7.8807607374168 no_core_fci_energy = numpy.linalg.eigh( self.hamiltonian_matrix_no_core.toarray())[0][0] self.assertAlmostEqual(no_core_fci_energy, self.frozen_core_fci_energy) # Check that the freeze_orbitals function has the same effect as the # as the occupied_indices option of get_molecular_hamiltonian. frozen_hamiltonian = freeze_orbitals( get_fermion_operator(self.molecular_hamiltonian), [0, 1]) self.assertTrue(frozen_hamiltonian == get_fermion_operator( self.molecular_hamiltonian_no_core))
def test_reverse_jw_too_few_n_qubits(self): with self.assertRaises(ValueError): reverse_jordan_wigner(self.operator_a, 0)