diff --git a/setup.py b/setup.py index 33fe33db4..c3ea535ba 100755 --- a/setup.py +++ b/setup.py @@ -11,26 +11,28 @@ # limitations under the License. import os +import runpy from setuptools import find_packages, setup # This reads the __version__ variable from openfermion/_version.py -__version__ = '' -exec(open('src/openfermion/_version.py').read()) +__version__ = runpy.run_path('src/openfermion/_version.py')['__version__'] +assert __version__, 'Version string cannot be empty' -# Readme file as long_description: +# The readme file is used as the long_description: long_description = '===========\n' + 'OpenFermion\n' + '===========\n\n' with open('README.rst', 'r', encoding='utf-8') as readme: long_description += readme.read() -# Read in package requirements.txt -requirements = open('dev_tools/requirements/deps/runtime.txt').readlines() +# Read in package requirements.txt. +with open('dev_tools/requirements/deps/runtime.txt') as r: + requirements = r.readlines() requirements = [r.strip() for r in requirements] requirements = [r for r in requirements if not r.startswith('#')] -# Resource estimates requirements. -resource_requirements = open( - 'dev_tools/requirements/deps/resource_estimates_runtime.txt' -).readlines() + +# Read in resource estimates requirements. +with open('dev_tools/requirements/deps/resource_estimates_runtime.txt') as r: + resource_requirements = r.readlines() resource_requirements = [r.strip() for r in resource_requirements] resource_requirements = [r for r in resource_requirements if not r.startswith('#')] diff --git a/src/openfermion/chem/molecular_data.py b/src/openfermion/chem/molecular_data.py index 82789b7cc..94c02e772 100644 --- a/src/openfermion/chem/molecular_data.py +++ b/src/openfermion/chem/molecular_data.py @@ -841,6 +841,7 @@ def save(self): try: os.remove("{}.hdf5".format(self.filename)) except OSError: + # Nothing to do but carry on. pass shutil.move("{}.hdf5".format(tmp_name), "{}.hdf5".format(self.filename)) diff --git a/src/openfermion/chem/molecular_data_test.py b/src/openfermion/chem/molecular_data_test.py index a6c222d10..e17ac7038 100644 --- a/src/openfermion/chem/molecular_data_test.py +++ b/src/openfermion/chem/molecular_data_test.py @@ -81,9 +81,7 @@ def test_name_molecule(self): # Check errors in naming with self.assertRaises(TypeError): - test_molecule = MolecularData( - self.geometry, self.basis, self.multiplicity, description=5 - ) + MolecularData(self.geometry, self.basis, self.multiplicity, description=5) correct_name = str('H2_sto-3g_singlet') test_molecule = self.molecule = MolecularData( self.geometry, self.basis, self.multiplicity, data_directory=DATA_DIRECTORY @@ -222,11 +220,9 @@ def test_active_space(self): """Test simple active space truncation features""" # Start w/ no truncation - ( - core_const, - one_body_integrals, - two_body_integrals, - ) = self.molecule.get_active_space_integrals(active_indices=[0, 1]) + (core_const, one_body_integrals, two_body_integrals) = ( + self.molecule.get_active_space_integrals(active_indices=[0, 1]) + ) self.assertAlmostEqual(core_const, 0.0) self.assertAlmostEqual( diff --git a/src/openfermion/circuits/gates/four_qubit_gates.py b/src/openfermion/circuits/gates/four_qubit_gates.py index 59baddabe..401d378f7 100644 --- a/src/openfermion/circuits/gates/four_qubit_gates.py +++ b/src/openfermion/circuits/gates/four_qubit_gates.py @@ -120,8 +120,10 @@ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.Circ if args.use_unicode_characters: wire_symbols = ('⇅', '⇅', '⇵', '⇵') else: - # pylint: disable=anomalous-backslash-in-string - wire_symbols = (r'/\ \/', r'/\ \/', '\/ /\\', '\/ /\\') + up_down = r'/\ \/' + # Split up this string to avoid SyntaxError in Python 3.12. + down_up = r'\/ /' + '\\' + wire_symbols = (up_down, up_down, down_up, down_up) return cirq.CircuitDiagramInfo( wire_symbols=wire_symbols, exponent=self._diagram_exponent(args) ) diff --git a/src/openfermion/circuits/primitives/optimal_givens_decomposition_test.py b/src/openfermion/circuits/primitives/optimal_givens_decomposition_test.py index f386cf2d7..414e30acd 100644 --- a/src/openfermion/circuits/primitives/optimal_givens_decomposition_test.py +++ b/src/openfermion/circuits/primitives/optimal_givens_decomposition_test.py @@ -106,7 +106,6 @@ def test_col_eliminate(): # mixing U[1, 0] and U[0, 0] unitary_original = unitary.copy() gmat = givens_matrix_elements(unitary[0, 0], unitary[1, 0], which='right') - vec = numpy.array([[unitary[0, 0]], [unitary[1, 0]]]) fullgmat = create_givens(gmat, 0, 1, 3) zeroed_unitary = fullgmat.dot(unitary) diff --git a/src/openfermion/linalg/erpa.py b/src/openfermion/linalg/erpa.py index b93cbb057..84572aa29 100644 --- a/src/openfermion/linalg/erpa.py +++ b/src/openfermion/linalg/erpa.py @@ -1,4 +1,5 @@ """Code to generate the eigenvalue problem for the ERPA equations""" + from typing import Dict, Tuple, Union from itertools import product import numpy @@ -11,7 +12,7 @@ def erpa_eom_hamiltonian( h_ijkl: numpy.ndarray, tpdm: numpy.ndarray, p: int, q: int, r: int, s: int ) -> Union[float, complex]: - """ + r""" Evaluate $\sum_{a,b,c,d}h_{a, b, d, c}<\psi[p^ q, [a^ b^ c d, r^ s]]\psi>$ Args: diff --git a/src/openfermion/linalg/sparse_tools.py b/src/openfermion/linalg/sparse_tools.py index fcc93257d..28e5731a2 100644 --- a/src/openfermion/linalg/sparse_tools.py +++ b/src/openfermion/linalg/sparse_tools.py @@ -1162,6 +1162,8 @@ def single_quad_op_sparse(n_modes, mode, quadrature, hbar, trunc): op = numpy.sqrt(hbar / 2) * (b + b.conj().T) elif quadrature == 'p': op = -1j * numpy.sqrt(hbar / 2) * (b - b.conj().T) + else: + raise ValueError(f'Invalid value {quadrature} for quadrature parameter.') Id = [scipy.sparse.identity(trunc, dtype=complex, format='csc')] operator_list = Id * mode + [op] + Id * (n_modes - mode - 1) diff --git a/src/openfermion/linalg/sparse_tools_test.py b/src/openfermion/linalg/sparse_tools_test.py index 29be37fea..30a555e20 100644 --- a/src/openfermion/linalg/sparse_tools_test.py +++ b/src/openfermion/linalg/sparse_tools_test.py @@ -1192,6 +1192,11 @@ def test_single_quad_two_mode(self): expected = numpy.kron(self.Id, self.p) self.assertTrue(numpy.allclose(res, expected)) + def test_single_quad_op_sparse_invalid_quadrature(self): + """Test ValueError for invalid quadrature in single_quad_op_sparse.""" + with self.assertRaisesRegex(ValueError, "Invalid value x for quadrature parameter."): + single_quad_op_sparse(n_modes=1, mode=0, quadrature='x', hbar=1.0, trunc=2) + def test_boson_operator_sparse_trunc(self): op = BosonOperator('0') with self.assertRaises(ValueError): diff --git a/src/openfermion/linalg/wave_fitting.py b/src/openfermion/linalg/wave_fitting.py index 4cff2ad06..95f7566ff 100644 --- a/src/openfermion/linalg/wave_fitting.py +++ b/src/openfermion/linalg/wave_fitting.py @@ -40,7 +40,7 @@ def fit_known_frequencies( def prony(signal: numpy.ndarray) -> Tuple[numpy.ndarray, numpy.ndarray]: - """Estimates amplitudes and phases of a sparse signal using Prony's method. + r"""Estimates amplitudes and phases of a sparse signal using Prony's method. Single-ancilla quantum phase estimation returns a signal $g(k)=\sum (aj*exp(i*k*phij))$, where aj and phij are the amplitudes diff --git a/src/openfermion/linalg/wedge_product.py b/src/openfermion/linalg/wedge_product.py index 154332a13..f5ab17e9a 100644 --- a/src/openfermion/linalg/wedge_product.py +++ b/src/openfermion/linalg/wedge_product.py @@ -67,7 +67,7 @@ def generate_parity_permutations(seq): def wedge(left_tensor, right_tensor, left_index_ranks, right_index_ranks): - """ + r""" Implement the wedge product between left_tensor and right_tensor The wedge product is defined as diff --git a/src/openfermion/resource_estimates/molecule/pyscf_utils.py b/src/openfermion/resource_estimates/molecule/pyscf_utils.py index 4c22498f6..c0b070bcc 100644 --- a/src/openfermion/resource_estimates/molecule/pyscf_utils.py +++ b/src/openfermion/resource_estimates/molecule/pyscf_utils.py @@ -1,5 +1,5 @@ # coverage:ignore -""" Drivers for various PySCF electronic structure routines """ +"""Drivers for various PySCF electronic structure routines""" from typing import Tuple, Optional import sys import h5py @@ -82,6 +82,9 @@ def localize(pyscf_mf, loc_type='pm', verbose=0): loc_virt_mo = lo.ER(pyscf_mf.mol, pyscf_mf.mo_coeff[:, virt_idx]).kernel(verbose=verbose) print("DONE") + else: + raise ValueError(f'Invalid value {loc_type} for localization type parameter.') + # overwrite orbitals with localized orbitals pyscf_mf.mo_coeff[:, docc_idx] = loc_docc_mo.copy() pyscf_mf.mo_coeff[:, socc_idx] = loc_socc_mo.copy() diff --git a/src/openfermion/resource_estimates/pbc/thc/factorizations/thc_jax.py b/src/openfermion/resource_estimates/pbc/thc/factorizations/thc_jax.py index 45f9ce138..f644ba0dc 100644 --- a/src/openfermion/resource_estimates/pbc/thc/factorizations/thc_jax.py +++ b/src/openfermion/resource_estimates/pbc/thc/factorizations/thc_jax.py @@ -943,6 +943,7 @@ def kpoint_thc_via_isdf( if verbose: print("Time for BFGS {:.4f}".format(time.time() - start)) start = time.time() + opt_params = () if perform_adagrad_opt: if save_checkpoints: chkfile_name = f"{checkpoint_basename}_adagrad.h5" diff --git a/src/openfermion/resource_estimates/thc/spacetime.py b/src/openfermion/resource_estimates/thc/spacetime.py index 55c3d9204..8faac2127 100644 --- a/src/openfermion/resource_estimates/thc/spacetime.py +++ b/src/openfermion/resource_estimates/thc/spacetime.py @@ -28,9 +28,6 @@ def qubit_vs_toffoli(lam, dE, eps, n, chi, beta, M, algorithm='half', verbose=Fa verbose (bool) - do additional printing of intermediates? """ - # only valid algorithms accepted - assert algorithm in ['half', 'full'] - # The number of iterations for the phase estimation. iters = np.ceil(pi * lam / (dE * 2)) # The number of bits used for each register. @@ -487,8 +484,12 @@ def qubit_vs_toffoli(lam, dE, eps, n, chi, beta, M, algorithm='half', verbose=Fa colors = [color_dict[i] for i in labels] + else: + raise ValueError(f'Invalid value {algorithm} for algorithm parameter.') + # check lists are at least consistent - assert all(len(element) == len(tgates) for element in [qubits, labels, colors]) + if not all(len(element) == len(tgates) for element in [qubits, labels, colors]): + raise RuntimeError('Failed to get a consistent result.') return tgates, qubits, labels, colors @@ -579,10 +580,11 @@ def group_steps(labels, tgates, qubits): grouped_labels = ['R', 'QROM', 'I-QROM', 'QROM', 'R'] grouped_tgates = [ 13, 30, 14, 40, 20] (sum) grouped_qubits = [ 10, 30, 4, 70, 60] (mean) - """ - assert len(labels) == len(tgates) - assert len(labels) == len(qubits) + if len(labels) != len(tgates): + raise ValueError('Number of labels must equal number of Toffoli gates.') + if len(labels) != len(qubits): + raise ValueError('Number of labels must equal number of qubits.') # Key function -- group identical nearest neighbors in labels (x[0]) key_func = lambda x: x[0] @@ -604,5 +606,6 @@ def group_steps(labels, tgates, qubits): grouped_qubits.append(np.mean([i[1] for i in group])) # sanity check -- shouldn't be losing total value in toffoli - assert np.sum(tgates) == np.sum(grouped_tgates) + if np.sum(tgates) != np.sum(grouped_tgates): + raise RuntimeError('Sum of Toffoli gates does not equal sum of grouped gates.') return grouped_labels, grouped_tgates, grouped_qubits diff --git a/src/openfermion/transforms/opconversions/term_reordering.py b/src/openfermion/transforms/opconversions/term_reordering.py index ba9652a02..f7a59ab3e 100644 --- a/src/openfermion/transforms/opconversions/term_reordering.py +++ b/src/openfermion/transforms/opconversions/term_reordering.py @@ -189,6 +189,8 @@ def normal_ordered_ladder_term(term, coefficient, parity=-1): Op = FermionOperator elif parity == 1: Op = BosonOperator + else: + raise ValueError(f'Invalid value {parity} for parity parameter') ordered_term = Op() diff --git a/src/openfermion/transforms/opconversions/term_reordering_test.py b/src/openfermion/transforms/opconversions/term_reordering_test.py index 0e4d446d4..0a75205c8 100644 --- a/src/openfermion/transforms/opconversions/term_reordering_test.py +++ b/src/openfermion/transforms/opconversions/term_reordering_test.py @@ -23,6 +23,7 @@ from openfermion.transforms.opconversions.term_reordering import ( normal_ordered, + normal_ordered_ladder_term, chemist_ordered, reorder, ) @@ -221,6 +222,22 @@ def test_exceptions(self): with self.assertRaises(TypeError): _ = normal_ordered(1) + def test_normal_ordered_ladder_term_invalid_parity(self): + term = ((0, 1), (1, 0)) + coefficient = 1.0 + invalid_parity_1 = 2 + invalid_parity_2 = -2 + + with self.assertRaisesRegex( + ValueError, f"Invalid value {invalid_parity_1} for parity parameter" + ): + normal_ordered_ladder_term(term, coefficient, parity=invalid_parity_1) + + with self.assertRaisesRegex( + ValueError, f"Invalid value {invalid_parity_2} for parity parameter" + ): + normal_ordered_ladder_term(term, coefficient, parity=invalid_parity_2) + class TestReorder(unittest.TestCase): def test_reorder(self): diff --git a/src/openfermion/utils/bch_expansion.py b/src/openfermion/utils/bch_expansion.py index d2a2f1770..514118b4b 100644 --- a/src/openfermion/utils/bch_expansion.py +++ b/src/openfermion/utils/bch_expansion.py @@ -16,7 +16,7 @@ def bch_expand(*ops, **kwargs): - """Compute $\log[e^{x_1} ... e^{x_N}]$ using the BCH formula. + r"""Compute $\log[e^{x_1} ... e^{x_N}]$ using the BCH formula. This implementation is explained in arXiv:1712.01348. @@ -65,7 +65,7 @@ def _bch_expand_multiple_terms(*ops, **kwargs): def _bch_expand_two_terms(x, y, order=6): - """Compute $\log[e^x e^y]$ using the Baker-Campbell-Hausdorff formula. + r"""Compute $\log[e^x e^y]$ using the Baker-Campbell-Hausdorff formula. Args: x: An operator for which multiplication and addition are supported.