def test_hermiticity(self): n_orbitals = 5 # Real, no spin iop = random_interaction_operator(n_orbitals, real=True) ferm_op = get_fermion_operator(iop) self.assertTrue(is_hermitian(ferm_op)) # Real, spin iop = random_interaction_operator(n_orbitals, expand_spin=True, real=True) ferm_op = get_fermion_operator(iop) self.assertTrue(is_hermitian(ferm_op)) # Complex, no spin iop = random_interaction_operator(n_orbitals, real=False) ferm_op = get_fermion_operator(iop) self.assertTrue(is_hermitian(ferm_op)) # Complex, spin iop = random_interaction_operator(n_orbitals, expand_spin=True, real=False) ferm_op = get_fermion_operator(iop) self.assertTrue(is_hermitian(ferm_op))
def test_random_operators_are_reproducible(self): op1 = random_diagonal_coulomb_hamiltonian(5, seed=5947) op2 = random_diagonal_coulomb_hamiltonian(5, seed=5947) numpy.testing.assert_allclose(op1.one_body, op2.one_body) numpy.testing.assert_allclose(op1.two_body, op2.two_body) op1 = random_interaction_operator(5, seed=8911) op2 = random_interaction_operator(5, seed=8911) numpy.testing.assert_allclose(op1.one_body_tensor, op2.one_body_tensor) numpy.testing.assert_allclose(op1.two_body_tensor, op2.two_body_tensor) op1 = random_quadratic_hamiltonian(5, seed=17711) op2 = random_quadratic_hamiltonian(5, seed=17711) numpy.testing.assert_allclose(op1.combined_hermitian_part, op2.combined_hermitian_part) numpy.testing.assert_allclose(op1.antisymmetric_part, op2.antisymmetric_part) op1 = random_antisymmetric_matrix(5, seed=24074) op2 = random_antisymmetric_matrix(5, seed=24074) numpy.testing.assert_allclose(op1, op2) op1 = random_hermitian_matrix(5, seed=56753) op2 = random_hermitian_matrix(5, seed=56753) numpy.testing.assert_allclose(op1, op2) op1 = random_unitary_matrix(5, seed=56486) op2 = random_unitary_matrix(5, seed=56486) numpy.testing.assert_allclose(op1, op2)
def test_consistency(self): """Test consistency with JW for FermionOperators.""" # Random interaction operator n_qubits = 5 iop = random_interaction_operator(n_qubits, real=False) op1 = jordan_wigner(iop) op2 = jordan_wigner(get_fermion_operator(iop)) self.assertEqual(op1, op2) # Interaction operator from molecule geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))] basis = 'sto-3g' multiplicity = 1 filename = os.path.join(DATA_DIRECTORY, 'H1-Li1_sto-3g_singlet_1.45') molecule = MolecularData(geometry, basis, multiplicity, filename=filename) molecule.load() iop = molecule.get_molecular_hamiltonian() op1 = jordan_wigner(iop) op2 = jordan_wigner(get_fermion_operator(iop)) self.assertEqual(op1, op2)
def test_symmetry(self): n_orbitals = 5 # Real. iop = random_interaction_operator(n_orbitals, expand_spin=False, real=True) ferm_op = get_fermion_operator(iop) self.assertTrue(is_hermitian(ferm_op)) two_body_coefficients = iop.two_body_tensor for p, q, r, s in itertools.product(range(n_orbitals), repeat=4): self.assertAlmostEqual(two_body_coefficients[p, q, r, s], two_body_coefficients[r, q, p, s]) self.assertAlmostEqual(two_body_coefficients[p, q, r, s], two_body_coefficients[p, s, r, q]) self.assertAlmostEqual(two_body_coefficients[p, q, r, s], two_body_coefficients[s, r, q, p]) self.assertAlmostEqual(two_body_coefficients[p, q, r, s], two_body_coefficients[q, p, s, r]) self.assertAlmostEqual(two_body_coefficients[p, q, r, s], two_body_coefficients[r, s, p, q]) self.assertAlmostEqual(two_body_coefficients[p, q, r, s], two_body_coefficients[s, p, q, r]) self.assertAlmostEqual(two_body_coefficients[p, q, r, s], two_body_coefficients[q, r, s, p])
def test_interaction_operator(self): for n_orbitals, real, _ in itertools.product((1, 2, 5), (True, False), range(5)): operator = random_interaction_operator(n_orbitals, real=real) normal_ordered_operator = normal_ordered(operator) expected_qubit_operator = jordan_wigner(operator) actual_qubit_operator = jordan_wigner(normal_ordered_operator) assert expected_qubit_operator == actual_qubit_operator two_body_tensor = normal_ordered_operator.two_body_tensor n_orbitals = len(two_body_tensor) ones = numpy.ones((n_orbitals,) * 2) triu = numpy.triu(ones, 1) shape = (n_orbitals**2, 1) mask = (triu.reshape(shape) * ones.reshape(shape[::-1]) + ones.reshape(shape) * triu.reshape(shape[::-1])).reshape( (n_orbitals,) * 4) assert numpy.allclose(mask * two_body_tensor, numpy.zeros((n_orbitals,) * 4)) for term in normal_ordered_operator: order = len(term) // 2 left_term, right_term = term[:order], term[order:] assert all(i[1] == 1 for i in left_term) assert all(i[1] == 0 for i in right_term) assert left_term == tuple(sorted(left_term, reverse=True)) assert right_term == tuple(sorted(right_term, reverse=True))
def random_interaction_operator_term( order: int, real: bool = True, seed: Optional[int] = None, ) -> 'openfermion.InteractionOperator': """Generates a random interaction operator with non-zero coefficients only on terms corresponding to the given number of unique orbitals. The number of orbitals is equal to the given order. Args: order: How many unique orbitals the non-zero terms should correspond to. real: Whether or not the coefficients should be real. Defaults to True. seed: The seed. If None (default), uses np.random. """ n_orbitals = order if order > 4: return ops.InteractionOperator.zero(order) operator = random_interaction_operator(n_orbitals, real=real, seed=seed) operator.constant = 0 for indices in itertools.product(range(n_orbitals), repeat=2): if len(set(indices)) != order: operator.one_body_tensor[indices] = 0 for indices in itertools.product(range(n_orbitals), repeat=4): if len(set(indices)) != order: operator.two_body_tensor[indices] = 0 return operator
def test_hermitian_conjugated_interaction_operator(self): for n_orbitals, _ in itertools.product((1, 2, 5), range(5)): operator = random_interaction_operator(n_orbitals) qubit_operator = jordan_wigner(operator) conjugate_operator = hermitian_conjugated(operator) conjugate_qubit_operator = jordan_wigner(conjugate_operator) assert hermitian_conjugated(qubit_operator) == \ conjugate_qubit_operator
def test_consistency_for_complex_numbers(self): """Test consistency with JW for FermionOperators.""" # Random interaction operator n_qubits = 8 iop = random_interaction_operator(n_qubits, real=False) op1 = bravyi_kitaev(iop) op2 = bravyi_kitaev(get_fermion_operator(iop)) self.assertEqual(op1, op2)
def test_exception(self): n_qubits = 6 random_operator = get_fermion_operator( random_interaction_operator(n_qubits)) bad_term = ((2, 1), (3, 1)) random_operator += FermionOperator(bad_term) with self.assertRaises(OperatorSpecificationError): chemist_ordered(random_operator)
def test_convert_forward_back(self): n_qubits = 6 random_operator = get_fermion_operator( random_interaction_operator(n_qubits)) chemist_operator = chemist_ordered(random_operator) normalized_chemist = normal_ordered(chemist_operator) difference = normalized_chemist - normal_ordered(random_operator) self.assertAlmostEqual(0., difference.induced_norm())
def test_operator_consistency_w_spin(self): # Initialize a random InteractionOperator and FermionOperator. n_orbitals = 3 n_qubits = 2 * n_orbitals random_interaction = random_interaction_operator(n_orbitals, expand_spin=True, real=False, seed=8) random_fermion = get_fermion_operator(random_interaction) # Convert to chemist ordered tensor. one_body_correction, chemist_tensor = \ get_chemist_two_body_coefficients( random_interaction.two_body_tensor, spin_basis=True) # Convert output to FermionOperator. output_operator = FermionOperator((), random_interaction.constant) # Convert one-body. one_body_coefficients = (random_interaction.one_body_tensor + one_body_correction) for p, q in itertools.product(range(n_qubits), repeat=2): term = ((p, 1), (q, 0)) coefficient = one_body_coefficients[p, q] output_operator += FermionOperator(term, coefficient) # Convert two-body. for p, q, r, s in itertools.product(range(n_orbitals), repeat=4): coefficient = chemist_tensor[p, q, r, s] # Mixed spin. term = ((2 * p, 1), (2 * q, 0), (2 * r + 1, 1), (2 * s + 1, 0)) output_operator += FermionOperator(term, coefficient) term = ((2 * p + 1, 1), (2 * q + 1, 0), (2 * r, 1), (2 * s, 0)) output_operator += FermionOperator(term, coefficient) # Same spin. term = ((2 * p, 1), (2 * q, 0), (2 * r, 1), (2 * s, 0)) output_operator += FermionOperator(term, coefficient) term = ((2 * p + 1, 1), (2 * q + 1, 0), (2 * r + 1, 1), (2 * s + 1, 0)) output_operator += FermionOperator(term, coefficient) # Check that difference is small. difference = normal_ordered(random_fermion - output_operator) self.assertAlmostEqual(0., difference.induced_norm())
def test_form(self): n_qubits = 6 random_operator = get_fermion_operator( random_interaction_operator(n_qubits)) chemist_operator = chemist_ordered(random_operator) for term, _ in chemist_operator.terms.items(): if len(term) == 2 or not len(term): pass else: self.assertTrue(term[0][1]) self.assertTrue(term[2][1]) self.assertFalse(term[1][1]) self.assertFalse(term[3][1]) self.assertTrue(term[0][0] > term[2][0]) self.assertTrue(term[1][0] > term[3][0])
def benchmark_jordan_wigner_sparse(n_qubits): """Benchmark the speed at which a FermionOperator is mapped to a matrix. Args: n_qubits: The number of qubits in the example. Returns: runtime: The time in seconds that the benchmark took. """ # Initialize a random FermionOperator. molecular_operator = random_interaction_operator(n_qubits) fermion_operator = get_fermion_operator(molecular_operator) # Map to SparseOperator class. start_time = time.time() _ = jordan_wigner_sparse(fermion_operator) runtime = time.time() - start_time return runtime
def benchmark_molecular_operator_jordan_wigner(n_qubits): """Test speed with which molecular operators transform to qubit operators. Args: n_qubits: The size of the molecular operator instance. Ideally, we would be able to transform to a qubit operator for 50 qubit instances in less than a minute. We are way too slow right now. Returns: runtime: The number of seconds required to make the conversion. """ # Get an instance of InteractionOperator. molecular_operator = random_interaction_operator(n_qubits) # Convert to a qubit operator. start = time.time() _ = jordan_wigner(molecular_operator) end = time.time() # Return runtime. runtime = end - start return runtime
def test_random_operator_consistency(self): # Initialize a random InteractionOperator and FermionOperator. n_orbitals = 3 n_qubits = 2 * n_orbitals random_interaction = random_interaction_operator(n_orbitals, expand_spin=True, real=True, seed=8) random_fermion = get_fermion_operator(random_interaction) # Decompose. eigenvalues, one_body_squares, one_body_correction, error = ( low_rank_two_body_decomposition( random_interaction.two_body_tensor)) self.assertFalse(error) # Build back operator constant and one-body components. decomposed_operator = FermionOperator((), random_interaction.constant) one_body_coefficients = (random_interaction.one_body_tensor + one_body_correction) for p, q in itertools.product(range(n_qubits), repeat=2): term = ((p, 1), (q, 0)) coefficient = one_body_coefficients[p, q] decomposed_operator += FermionOperator(term, coefficient) # Build back two-body component. for l in range(n_orbitals**2): 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] one_body_operator += FermionOperator(term, coefficient) decomposed_operator += eigenvalues[l] * (one_body_operator**2) # Test for consistency. difference = normal_ordered(decomposed_operator - random_fermion) self.assertAlmostEqual(0., difference.induced_norm())