From 945bcaf56e554a52c4c37cfb7122724e74ce897c Mon Sep 17 00:00:00 2001 From: Fionn Malone Date: Thu, 3 Aug 2023 21:14:24 -0700 Subject: [PATCH] Enable testing for resource estimates (#828) * Guard imports and skip tests if pyscf / jax not found. * Upgrade ci to run resource estimate tests. * Remove commented code. * Fix formatting. * Fix requirements filename. * Remove argument from workflow. * Remove comments from ci. * Fix ci and ignore init in coverage. * Attempt to fix windows issue using shorter ints. * Fix formatting and overflow. * Add rootdir to check/pytest. --- .github/workflows/ci.yml | 21 ++ .gitignore | 2 + check/pytest | 8 +- dev_tools/conf/pytest.ini | 3 + .../requirements/deps/resource_estimates.txt | 3 + dev_tools/requirements/re-pip-compile.sh | 1 + .../requirements/resource_estimates.env.txt | 218 ++++++++++++++++++ .../resource_estimates/__init__.py | 10 +- .../resource_estimates/df/__init__.py | 11 +- .../df/compute_cost_df_test.py | 11 +- .../df/compute_lambda_df_test.py | 11 +- .../resource_estimates/molecule/__init__.py | 20 +- .../molecule/pyscf_utils_test.py | 31 ++- .../resource_estimates/sf/__init__.py | 11 +- .../sf/compute_cost_sf_test.py | 11 +- .../sf/compute_lambda_sf_test.py | 11 +- .../sf/generate_costing_table_sf.py | 16 +- .../resource_estimates/sparse/__init__.py | 1 - .../sparse/costing_sparse.py | 1 - .../sparse/costing_sparse_test.py | 1 - .../resource_estimates/thc/__init__.py | 13 +- .../thc/compute_cost_thc_test.py | 1 + .../thc/compute_lambda_thc_test.py | 12 +- .../resource_estimates/thc/factorize_thc.py | 9 +- .../thc/generate_costing_table_thc.py | 14 +- .../resource_estimates/thc/utils/__init__.py | 20 +- src/openfermion/resource_estimates/utils.py | 21 +- 27 files changed, 396 insertions(+), 96 deletions(-) create mode 100644 dev_tools/conf/pytest.ini create mode 100644 dev_tools/requirements/deps/resource_estimates.txt create mode 100644 dev_tools/requirements/resource_estimates.env.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7931bc576..b178a2cb0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,6 +71,27 @@ jobs: - name: Pytest check run: check/pytest shell: bash + pytest_resource_estimates: + name: Pytest Resource Estimates + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + python-version: [ '3.10' ] + cirq-version: [ '~=1.0' ] + fail-fast: false + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install requirements + run: | + pip install -r dev_tools/requirements/resource_estimates.env.txt + pip install cirq-core${{matrix.cirq-version}} + - name: Pytest check resources + run: check/pytest -m 'not slow' src/openfermion/resource_estimates + shell: bash coverage: name: Coverage check runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 122ce4bf9..e6ba1d5be 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,5 @@ ENV/ # no .dat files *.dat + +*tmp* diff --git a/check/pytest b/check/pytest index 5e1af16a5..dc21dd585 100755 --- a/check/pytest +++ b/check/pytest @@ -17,9 +17,11 @@ cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$(git rev-parse --show-toplevel)" +rootdir=$(pwd) + PYTEST_ARGS=() ACTUALLY_QUIET="" -for arg in $@; do +for arg in "$@"; do if [[ "${arg}" == "--actually-quiet" ]]; then ACTUALLY_QUIET=1 else @@ -28,10 +30,10 @@ for arg in $@; do done if [ -z "${ACTUALLY_QUIET}" ]; then - pytest "${PYTEST_ARGS[@]}" + pytest -c dev_tools/conf/pytest.ini --rootdir=$rootdir "${PYTEST_ARGS[@]}" else # Filter out lines like "...F....x... [ 42%]", with coloring. - pytest -q --color=yes "${PYTEST_ARGS[@]}" | + pytest -c dev_tools/conf/pytest.ini --rootdir=$rootdir -q --color=yes "${PYTEST_ARGS[@]}" | grep -Pv '^(.\[0m)?[\.FEsx]+(.\[36m)?\s+\[\s*\d+%\](.\[0m)?$' exit "${PIPESTATUS[0]}" fi diff --git a/dev_tools/conf/pytest.ini b/dev_tools/conf/pytest.ini new file mode 100644 index 000000000..761785364 --- /dev/null +++ b/dev_tools/conf/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +markers = + slow: marks tests as slow (deselect with '-m "not slow"') diff --git a/dev_tools/requirements/deps/resource_estimates.txt b/dev_tools/requirements/deps/resource_estimates.txt new file mode 100644 index 000000000..2a580db7c --- /dev/null +++ b/dev_tools/requirements/deps/resource_estimates.txt @@ -0,0 +1,3 @@ +pyscf +jax +jaxlib diff --git a/dev_tools/requirements/re-pip-compile.sh b/dev_tools/requirements/re-pip-compile.sh index 513ce2ee6..2abd2f6e7 100644 --- a/dev_tools/requirements/re-pip-compile.sh +++ b/dev_tools/requirements/re-pip-compile.sh @@ -11,3 +11,4 @@ pip-compile $@ --output-file=pylint.env.txt --resolver=backtracking deps/pylint. pip-compile $@ --output-file=pytest.env.txt --resolver=backtracking deps/pytest.txt runtime.env.txt pip-compile $@ --output-file=mypy.env.txt --resolver=backtracking deps/mypy.txt runtime.env.txt pip-compile $@ --output-file=dev.env.txt --resolver=backtracking deps/dev-tools.txt runtime.env.txt +pip-compile $@ --output-file=dev.env.txt --resolver=backtracking deps/resource_estimates.txt pytest.env.txt diff --git a/dev_tools/requirements/resource_estimates.env.txt b/dev_tools/requirements/resource_estimates.env.txt new file mode 100644 index 000000000..68b7b494d --- /dev/null +++ b/dev_tools/requirements/resource_estimates.env.txt @@ -0,0 +1,218 @@ +# +# This file is autogenerated by pip-compile with Python 3.10 +# by the following command: +# +# pip-compile --output-file=resource_estimates.env.txt deps/resource_estimates.txt pytest.env.txt +# +attrs==23.1.0 + # via + # -r pytest.env.txt + # jsonschema +certifi==2023.5.7 + # via + # -r pytest.env.txt + # requests +charset-normalizer==3.1.0 + # via + # -r pytest.env.txt + # requests +cirq-core==1.1.0 + # via -r pytest.env.txt +contourpy==1.0.7 + # via + # -r pytest.env.txt + # matplotlib +coverage[toml]==7.2.5 + # via + # -r pytest.env.txt + # pytest-cov +cycler==0.11.0 + # via + # -r pytest.env.txt + # matplotlib +deprecation==2.1.0 + # via -r pytest.env.txt +duet==0.2.8 + # via + # -r pytest.env.txt + # cirq-core +exceptiongroup==1.1.1 + # via + # -r pytest.env.txt + # pytest +execnet==1.9.0 + # via + # -r pytest.env.txt + # pytest-xdist +fastjsonschema==2.17.1 + # via + # -r pytest.env.txt + # nbformat +fonttools==4.39.4 + # via + # -r pytest.env.txt + # matplotlib +h5py==3.8.0 + # via + # -r pytest.env.txt + # pyscf +idna==3.4 + # via + # -r pytest.env.txt + # requests +iniconfig==2.0.0 + # via + # -r pytest.env.txt + # pytest +jax==0.4.14 + # via -r deps/resource_estimates.txt +jaxlib==0.4.14 + # via -r deps/resource_estimates.txt +jsonschema==4.17.3 + # via + # -r pytest.env.txt + # nbformat +jupyter-core==5.3.0 + # via + # -r pytest.env.txt + # nbformat +kiwisolver==1.4.4 + # via + # -r pytest.env.txt + # matplotlib +matplotlib==3.7.1 + # via + # -r pytest.env.txt + # cirq-core +ml-dtypes==0.2.0 + # via + # jax + # jaxlib +mpmath==1.3.0 + # via + # -r pytest.env.txt + # sympy +nbformat==5.8.0 + # via -r pytest.env.txt +networkx==2.8.8 + # via + # -r pytest.env.txt + # cirq-core +numpy==1.23.5 + # via + # -r pytest.env.txt + # cirq-core + # contourpy + # h5py + # jax + # jaxlib + # matplotlib + # ml-dtypes + # opt-einsum + # pandas + # pyscf + # scipy +opt-einsum==3.3.0 + # via jax +packaging==23.1 + # via + # -r pytest.env.txt + # deprecation + # matplotlib + # pytest +pandas==2.0.1 + # via + # -r pytest.env.txt + # cirq-core +pillow==9.5.0 + # via + # -r pytest.env.txt + # matplotlib +platformdirs==3.5.1 + # via + # -r pytest.env.txt + # jupyter-core +pluggy==1.0.0 + # via + # -r pytest.env.txt + # pytest +pubchempy==1.0.4 + # via -r pytest.env.txt +pyparsing==3.0.9 + # via + # -r pytest.env.txt + # matplotlib +pyrsistent==0.19.3 + # via + # -r pytest.env.txt + # jsonschema +pyscf==2.3.0 + # via -r deps/resource_estimates.txt +pytest==7.3.1 + # via + # -r pytest.env.txt + # pytest-asyncio + # pytest-cov + # pytest-xdist +pytest-asyncio==0.21.0 + # via -r pytest.env.txt +pytest-cov==4.0.0 + # via -r pytest.env.txt +pytest-xdist==3.3.1 + # via -r pytest.env.txt +python-dateutil==2.8.2 + # via + # -r pytest.env.txt + # matplotlib + # pandas +pytz==2023.3 + # via + # -r pytest.env.txt + # pandas +requests==2.31.0 + # via -r pytest.env.txt +scipy==1.9.3 + # via + # -r pytest.env.txt + # cirq-core + # jax + # jaxlib + # pyscf +six==1.16.0 + # via + # -r pytest.env.txt + # python-dateutil +sortedcontainers==2.4.0 + # via + # -r pytest.env.txt + # cirq-core +sympy==1.12 + # via + # -r pytest.env.txt + # cirq-core +tomli==2.0.1 + # via + # -r pytest.env.txt + # coverage + # pytest +tqdm==4.65.0 + # via + # -r pytest.env.txt + # cirq-core +traitlets==5.9.0 + # via + # -r pytest.env.txt + # jupyter-core + # nbformat +typing-extensions==4.6.0 + # via + # -r pytest.env.txt + # cirq-core +tzdata==2023.3 + # via + # -r pytest.env.txt + # pandas +urllib3==2.0.2 + # via + # -r pytest.env.txt + # requests diff --git a/src/openfermion/resource_estimates/__init__.py b/src/openfermion/resource_estimates/__init__.py index d91d98e2f..70e476466 100644 --- a/src/openfermion/resource_estimates/__init__.py +++ b/src/openfermion/resource_estimates/__init__.py @@ -1,4 +1,4 @@ -#coverage:ignore +# coverage:ignore # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -10,10 +10,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -#coverage: ignore -import pytest try: + import jax import pyscf -except ImportError: - pytest.skip('Need pyscf for resource estimates', allow_module_level=True) + HAVE_DEPS_FOR_RESOURCE_ESTIMATES = True +except ModuleNotFoundError: + HAVE_DEPS_FOR_RESOURCE_ESTIMATES = False diff --git a/src/openfermion/resource_estimates/df/__init__.py b/src/openfermion/resource_estimates/df/__init__.py index e8fbffdfc..c8888221d 100644 --- a/src/openfermion/resource_estimates/df/__init__.py +++ b/src/openfermion/resource_estimates/df/__init__.py @@ -13,7 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .compute_lambda_df import compute_lambda -from .compute_cost_df import compute_cost -from .factorize_df import factorize -from .generate_costing_table_df import generate_costing_table +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES + +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from .compute_cost_df import compute_cost + from .compute_lambda_df import compute_lambda + from .factorize_df import factorize + from .generate_costing_table_df import generate_costing_table \ No newline at end of file diff --git a/src/openfermion/resource_estimates/df/compute_cost_df_test.py b/src/openfermion/resource_estimates/df/compute_cost_df_test.py index 762fa1728..6632a1446 100644 --- a/src/openfermion/resource_estimates/df/compute_cost_df_test.py +++ b/src/openfermion/resource_estimates/df/compute_cost_df_test.py @@ -1,9 +1,16 @@ #coverage:ignore """Test cases for costing_df.py """ -from openfermion.resource_estimates import df +import pytest +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from openfermion.resource_estimates import df + + +@pytest.mark.skipif(not HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + reason='pyscf and/or jax not installed.') def test_reiher_df(): """ Reproduce Reiher et al orbital DF FT costs from paper """ DE = 0.001 @@ -25,6 +32,8 @@ def test_reiher_df(): assert output == (21753, 10073183463, 3725) +@pytest.mark.skipif(not HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + reason='pyscf and/or jax not installed.') def test_li_df(): """ Reproduce Li et al orbital DF FT costs from paper """ DE = 0.001 diff --git a/src/openfermion/resource_estimates/df/compute_lambda_df_test.py b/src/openfermion/resource_estimates/df/compute_lambda_df_test.py index 7203b821d..c5a1403aa 100644 --- a/src/openfermion/resource_estimates/df/compute_lambda_df_test.py +++ b/src/openfermion/resource_estimates/df/compute_lambda_df_test.py @@ -2,11 +2,18 @@ """Test cases for compute_lambda_df.py """ from os import path + import numpy as np -from openfermion.resource_estimates import df -from openfermion.resource_estimates.molecule import load_casfile_to_pyscf +import pytest + +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES, df + +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from openfermion.resource_estimates.molecule import load_casfile_to_pyscf +@pytest.mark.skipif(not HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + reason="pyscf and/or jax not installed.") def test_reiher_df_lambda(): """ Reproduce Reiher et al orbital DF lambda from paper """ diff --git a/src/openfermion/resource_estimates/molecule/__init__.py b/src/openfermion/resource_estimates/molecule/__init__.py index 1aae53fdd..b9713f52c 100644 --- a/src/openfermion/resource_estimates/molecule/__init__.py +++ b/src/openfermion/resource_estimates/molecule/__init__.py @@ -11,16 +11,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .pyscf_utils import ( - stability, - localize, - avas_active_space, - cas_to_pyscf, - pyscf_to_cas, - get_num_active_alpha_beta, - load_casfile_to_pyscf, - save_pyscf_to_casfile, - factorized_ccsd_t, - ccsd_t, - open_shell_t1_d1, -) +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES + +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from .pyscf_utils import (avas_active_space, cas_to_pyscf, ccsd_t, + factorized_ccsd_t, get_num_active_alpha_beta, + load_casfile_to_pyscf, localize, open_shell_t1_d1, + pyscf_to_cas, save_pyscf_to_casfile, stability) diff --git a/src/openfermion/resource_estimates/molecule/pyscf_utils_test.py b/src/openfermion/resource_estimates/molecule/pyscf_utils_test.py index 27a50f6ad..c092efee2 100644 --- a/src/openfermion/resource_estimates/molecule/pyscf_utils_test.py +++ b/src/openfermion/resource_estimates/molecule/pyscf_utils_test.py @@ -1,29 +1,26 @@ #coverage:ignore """Test cases for pyscf_utils.py """ -from os import path import unittest -import pytest +from os import path + import numpy as np +import pytest + +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES -try: - from pyscf import gto, scf, cc - HAS_PYSCF = True -except ModuleNotFoundError: - # resource_estimates depend on pyscf, which may not be installed - HAS_PYSCF = False +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from pyscf import cc, gto, scf -if HAS_PYSCF: - from openfermion.resource_estimates import sf, df - from openfermion.resource_estimates.utils import QR, QI, QR2, QI2, power_two - from openfermion.resource_estimates.molecule import (load_casfile_to_pyscf, - pyscf_to_cas, ccsd_t, - stability, - factorized_ccsd_t, - open_shell_t1_d1) + from openfermion.resource_estimates import df, sf + from openfermion.resource_estimates.molecule import ( + ccsd_t, factorized_ccsd_t, load_casfile_to_pyscf, open_shell_t1_d1, + pyscf_to_cas, stability) -@pytest.mark.skipif(not HAS_PYSCF, reason='Not detecting `pyscf`.') +@pytest.mark.skipif(not HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + reason='pyscf and/or jax not installed.') +@pytest.mark.slow class OpenFermionPyscfUtilsTest(unittest.TestCase): def test_full_ccsd_t(self): diff --git a/src/openfermion/resource_estimates/sf/__init__.py b/src/openfermion/resource_estimates/sf/__init__.py index 09185450d..1825cf686 100644 --- a/src/openfermion/resource_estimates/sf/__init__.py +++ b/src/openfermion/resource_estimates/sf/__init__.py @@ -13,7 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .compute_lambda_sf import compute_lambda -from .compute_cost_sf import compute_cost -from .factorize_sf import factorize -from .generate_costing_table_sf import generate_costing_table +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES + +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from .compute_cost_sf import compute_cost + from .compute_lambda_sf import compute_lambda + from .factorize_sf import factorize + from .generate_costing_table_sf import generate_costing_table diff --git a/src/openfermion/resource_estimates/sf/compute_cost_sf_test.py b/src/openfermion/resource_estimates/sf/compute_cost_sf_test.py index ebd355106..340bcde0d 100644 --- a/src/openfermion/resource_estimates/sf/compute_cost_sf_test.py +++ b/src/openfermion/resource_estimates/sf/compute_cost_sf_test.py @@ -1,9 +1,16 @@ #coverage:ignore """Test cases for costing_sf.py """ -from openfermion.resource_estimates import sf +import pytest +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from openfermion.resource_estimates import sf + + +@pytest.mark.skipif(not HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + reason='pyscf and/or jax not installed.') def test_reiher_sf(): """ Reproduce Reiher et al orbital SF FT costs from paper """ DE = 0.001 @@ -23,6 +30,8 @@ def test_reiher_sf(): assert output == (14184, 94868988984, 3320) +@pytest.mark.skipif(not HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + reason='pyscf and/or jax not installed.') def test_li_sf(): """ Reproduce Li et al orbital SF FT costs from paper """ DE = 0.001 diff --git a/src/openfermion/resource_estimates/sf/compute_lambda_sf_test.py b/src/openfermion/resource_estimates/sf/compute_lambda_sf_test.py index 6b9092345..612ba8b5b 100644 --- a/src/openfermion/resource_estimates/sf/compute_lambda_sf_test.py +++ b/src/openfermion/resource_estimates/sf/compute_lambda_sf_test.py @@ -2,11 +2,18 @@ """Test cases for compute_lambda_sf.py """ from os import path + import numpy as np -from openfermion.resource_estimates import sf -from openfermion.resource_estimates.molecule import load_casfile_to_pyscf +import pytest + +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES, sf + +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from openfermion.resource_estimates.molecule import load_casfile_to_pyscf +@pytest.mark.skipif(not HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + reason='pyscf and/or jax not installed.') def test_reiher_sf_lambda(): """ Reproduce Reiher et al orbital SF lambda from paper """ diff --git a/src/openfermion/resource_estimates/sf/generate_costing_table_sf.py b/src/openfermion/resource_estimates/sf/generate_costing_table_sf.py index 7eadb94d1..003feafb5 100644 --- a/src/openfermion/resource_estimates/sf/generate_costing_table_sf.py +++ b/src/openfermion/resource_estimates/sf/generate_costing_table_sf.py @@ -1,12 +1,20 @@ #coverage:ignore """ Pretty-print a table comparing number of SF vectors versus acc and cost """ import numpy as np -from pyscf import scf -from openfermion.resource_estimates import sf -from openfermion.resource_estimates.molecule import (factorized_ccsd_t, - cas_to_pyscf, pyscf_to_cas) +import pytest +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES, sf +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from pyscf import scf + + from openfermion.resource_estimates.molecule import (cas_to_pyscf, + factorized_ccsd_t, + pyscf_to_cas) + + +@pytest.mark.skipif(not HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + reason='pyscf and/or jax not installed.') def generate_costing_table(pyscf_mf, name='molecule', rank_range=range(50, 401, 25), diff --git a/src/openfermion/resource_estimates/sparse/__init__.py b/src/openfermion/resource_estimates/sparse/__init__.py index 09839684a..4680861fd 100644 --- a/src/openfermion/resource_estimates/sparse/__init__.py +++ b/src/openfermion/resource_estimates/sparse/__init__.py @@ -1,4 +1,3 @@ -#coverage:ignore # Copyright 2020 Google LLC # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/src/openfermion/resource_estimates/sparse/costing_sparse.py b/src/openfermion/resource_estimates/sparse/costing_sparse.py index 767640c7d..a33f2c272 100644 --- a/src/openfermion/resource_estimates/sparse/costing_sparse.py +++ b/src/openfermion/resource_estimates/sparse/costing_sparse.py @@ -1,4 +1,3 @@ -#coverage:ignore """ Determine costs for sparse decomposition in QC Note this is WIP """ diff --git a/src/openfermion/resource_estimates/sparse/costing_sparse_test.py b/src/openfermion/resource_estimates/sparse/costing_sparse_test.py index 33c2adffd..0de9ad1b4 100644 --- a/src/openfermion/resource_estimates/sparse/costing_sparse_test.py +++ b/src/openfermion/resource_estimates/sparse/costing_sparse_test.py @@ -1,4 +1,3 @@ -#coverage:ignore """Test cases for costing_sparse.py """ from openfermion.resource_estimates.sparse.costing_sparse import cost_sparse diff --git a/src/openfermion/resource_estimates/thc/__init__.py b/src/openfermion/resource_estimates/thc/__init__.py index da686a035..2dadc8d94 100644 --- a/src/openfermion/resource_estimates/thc/__init__.py +++ b/src/openfermion/resource_estimates/thc/__init__.py @@ -12,14 +12,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import pytest -try: - import jax, pybtas - from .spacetime import qubit_vs_toffoli +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES + +from .compute_cost_thc import compute_cost +from .spacetime import qubit_vs_toffoli + +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: from .compute_lambda_thc import compute_lambda - from .compute_cost_thc import compute_cost from .factorize_thc import thc_via_cp3 as factorize from .generate_costing_table_thc import generate_costing_table -except ImportError: - pytest.skip('Need jax and pybtas for THC', allow_module_level=True) diff --git a/src/openfermion/resource_estimates/thc/compute_cost_thc_test.py b/src/openfermion/resource_estimates/thc/compute_cost_thc_test.py index 111ab4d2e..c2f4943ea 100644 --- a/src/openfermion/resource_estimates/thc/compute_cost_thc_test.py +++ b/src/openfermion/resource_estimates/thc/compute_cost_thc_test.py @@ -2,6 +2,7 @@ """Test cases for costing_thc.py """ import unittest + import pytest from openfermion.resource_estimates import thc diff --git a/src/openfermion/resource_estimates/thc/compute_lambda_thc_test.py b/src/openfermion/resource_estimates/thc/compute_lambda_thc_test.py index e43ee0307..5c7427d9e 100644 --- a/src/openfermion/resource_estimates/thc/compute_lambda_thc_test.py +++ b/src/openfermion/resource_estimates/thc/compute_lambda_thc_test.py @@ -1,12 +1,20 @@ #coverage:ignore import os + import h5py import numpy as np +import pytest + import openfermion.resource_estimates.integrals as int_folder -from openfermion.resource_estimates import thc -from openfermion.resource_estimates.molecule import load_casfile_to_pyscf +from openfermion.resource_estimates import (HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + thc) + +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from openfermion.resource_estimates.molecule import load_casfile_to_pyscf +@pytest.mark.skipif(not HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + reason='pyscf and/or jax not installed.') def test_lambda(): integral_path = int_folder.__file__.replace('__init__.py', '') thc_factor_file = os.path.join(integral_path, 'M_250_beta_16_eta_10.h5') diff --git a/src/openfermion/resource_estimates/thc/factorize_thc.py b/src/openfermion/resource_estimates/thc/factorize_thc.py index 0b2a2f837..3c2ac47a9 100644 --- a/src/openfermion/resource_estimates/thc/factorize_thc.py +++ b/src/openfermion/resource_estimates/thc/factorize_thc.py @@ -1,12 +1,11 @@ #coverage:ignore """ THC rank reduction of ERIs """ -import sys import time -import uuid -import numpy as np + import h5py -from openfermion.resource_estimates.thc.utils import (lbfgsb_opt_thc_l2reg, - adagrad_opt_thc) +import numpy as np + +from openfermion.resource_estimates.thc.utils import lbfgsb_opt_thc_l2reg def thc_via_cp3(eri_full, diff --git a/src/openfermion/resource_estimates/thc/generate_costing_table_thc.py b/src/openfermion/resource_estimates/thc/generate_costing_table_thc.py index 1d78acf9e..ec8278940 100644 --- a/src/openfermion/resource_estimates/thc/generate_costing_table_thc.py +++ b/src/openfermion/resource_estimates/thc/generate_costing_table_thc.py @@ -1,10 +1,16 @@ #coverage:ignore """ Pretty-print a table comparing number of THC vectors vs accy and cost """ import numpy as np -from pyscf import scf -from openfermion.resource_estimates import thc -from openfermion.resource_estimates.molecule import (factorized_ccsd_t, - cas_to_pyscf, pyscf_to_cas) + +from openfermion.resource_estimates import (HAVE_DEPS_FOR_RESOURCE_ESTIMATES, + thc) + +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from pyscf import scf + + from openfermion.resource_estimates.molecule import (cas_to_pyscf, + factorized_ccsd_t, + pyscf_to_cas) def generate_costing_table(pyscf_mf, diff --git a/src/openfermion/resource_estimates/thc/utils/__init__.py b/src/openfermion/resource_estimates/thc/utils/__init__.py index 26b33a8e0..f29620149 100644 --- a/src/openfermion/resource_estimates/thc/utils/__init__.py +++ b/src/openfermion/resource_estimates/thc/utils/__init__.py @@ -13,11 +13,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .thc_factorization import (lbfgsb_opt_thc, lbfgsb_opt_thc_l2reg, - adagrad_opt_thc, lbfgsb_opt_cholesky) -from .thc_objectives import (thc_objective_jax, thc_objective_grad_jax, - thc_objective, thc_objective_regularized, - thc_objective_grad, thc_objective_and_grad, - cp_ls_cholesky_factor_objective) -from .adagrad import (adagrad, constant, exponential_decay, inverse_time_decay, - polynomial_decay, piecewise_constant, make_schedule) +from openfermion.resource_estimates import HAVE_DEPS_FOR_RESOURCE_ESTIMATES + +if HAVE_DEPS_FOR_RESOURCE_ESTIMATES: + from .adagrad import (adagrad, constant, exponential_decay, + inverse_time_decay, make_schedule, piecewise_constant, + polynomial_decay) + from .thc_factorization import (adagrad_opt_thc, lbfgsb_opt_cholesky, + lbfgsb_opt_thc, lbfgsb_opt_thc_l2reg) + from .thc_objectives import (cp_ls_cholesky_factor_objective, thc_objective, + thc_objective_and_grad, thc_objective_grad, + thc_objective_grad_jax, thc_objective_jax, + thc_objective_regularized) \ No newline at end of file diff --git a/src/openfermion/resource_estimates/utils.py b/src/openfermion/resource_estimates/utils.py index 3deec27fb..3630788e1 100644 --- a/src/openfermion/resource_estimates/utils.py +++ b/src/openfermion/resource_estimates/utils.py @@ -23,10 +23,9 @@ def QR(L: int, M1: int) -> Tuple[int, int]: try: assert k >= 0 except AssertionError: - sys.exit("In function QR: \ - \n L is smaller than M: increase RANK or lower THRESH \ - (or alternatively decrease CHI)") - value = lambda k: L / np.power(2, k) + M1 * (np.power(2, k) - 1) + sys.exit("In function QR: L is smaller than M: increase RANK or lower " + "THRESH (or alternatively decrease CHI)") + value = lambda k: L / np.power(2.0, k) + M1 * (np.power(2.0, k) - 1) k_int = [np.floor(k), np.ceil(k)] # restrict optimal k to integers k_opt = k_int[np.argmin(value(k_int))] # obtain optimal k val_opt = np.ceil(value(k_opt)) # obtain ceiling of optimal value given k @@ -56,9 +55,9 @@ def QR2(L1: int, L2: int, M1: int) -> Tuple[int, int, int]: # Biggest concern is if k1 / k2 range is not large enough! for k1 in range(1, 17): for k2 in range(1, 17): - value = np.ceil(L1 / np.power(2, k1)) * np.ceil(L2 / \ - np.power(2, k2)) +\ - M1 * (np.power(2, k1 + k2) - 1) + value = np.ceil(L1 / np.power(2.0, k1)) * np.ceil(L2 / \ + np.power(2.0, k2)) +\ + M1 * (np.power(2.0, k1 + k2) - 1) if value < val_opt: val_opt = value k1_opt = k1 @@ -80,7 +79,7 @@ def QI(L: int) -> Tuple[int, int]: """ k = 0.5 * np.log2(L) assert k >= 0 - value = lambda k: L / np.power(2, k) + np.power(2, k) + value = lambda k: L / np.power(2.0, k) + np.power(2.0, k) k_int = [np.floor(k), np.ceil(k)] # restrict optimal k to integers k_opt = k_int[np.argmin(value(k_int))] # obtain optimal k val_opt = np.ceil(value(k_opt)) # obtain ceiling of optimal value given k @@ -111,9 +110,9 @@ def QI2(L1: int, L2: int) -> Tuple[int, int, int]: # Biggest concern is if k1 / k2 range is not large enough! for k1 in range(1, 17): for k2 in range(1, 17): - value = np.ceil(L1 / np.power(2, k1)) * np.ceil(L2 / \ - np.power(2, k2)) +\ - np.power(2, k1 + k2) + value = np.ceil(L1 / np.power(2.0, k1)) * np.ceil(L2 / \ + np.power(2.0, k2)) +\ + np.power(2.0, k1 + k2) if value < val_opt: val_opt = value k1_opt = k1