diff --git a/release/setup.py b/release/setup.py index e2b392eaf..4c15f1393 100644 --- a/release/setup.py +++ b/release/setup.py @@ -50,6 +50,14 @@ def finalize_options(self): "cirq-google==1.3.0", "sympy==1.14", "tf-keras~=2.16.0", + # The following are transitive dependencies that need to be constrained to + # avoid incompatible versions or because some (e.g., contourpy 1.3.3) + # require Python 3.11+ and we want to maintain Python 3.10 compatibility. + # TODO: revisit after we reach compatibility with TensorFlow 2.19+. + "contourpy<=1.3.2", + "jax<=0.5", + "numpy<2.0", + "scipy<=1.12.0", # The following makes it easier to get the right version on Colab. Once # TFQ works with the latest version of TF, this may become unnecessary. "protobuf==4.25.8", diff --git a/requirements-pins.txt b/requirements-pins.txt new file mode 100644 index 000000000..b7847c708 --- /dev/null +++ b/requirements-pins.txt @@ -0,0 +1,12 @@ +# Summary: requirements constraints for TensorFlow Quantum. +# +# This file is used to constrain the versions of transitive dependencies during +# the 'pip-compile' process. This is the recommended way to apply security +# patches without polluting requirements.in. +# +# This file currently requires manual updates when necessary, such as when +# Dependabot opens PRs to update a transitive dependency in requirements.txt. + +fonttools>=4.60.2 +urllib3>=2.6.0 +werkzeug>=3.1.4 diff --git a/requirements.in b/requirements.in index 92c987272..18e52d8f7 100644 --- a/requirements.in +++ b/requirements.in @@ -18,14 +18,18 @@ # scripts/generate_requirements.sh. cirq-core~=1.3.0 cirq-google~=1.3.0 +numpy<2.0 tensorflow>=2.16,<2.17 tf-keras~=2.16.0 +scipy<=1.12.0 +sympy==1.14 -# TODO: the next ones are not truly core requirements. A better place should be -# found for them (long with others needed by scripts/*). They're here as a -# stop-gap measure until then. -yapf==0.43.0 -pylint==3.3.3 -nbformat==5.1.3 -nbclient==0.6.5 -tensorflow-docs +# This needs to match what TensorFlow uses to avoid problems with distutils. +setuptools==68.2.2 + +# The rest are transitive dependencies that need to be constrained either +# because pip may try to install incompatible versions, or the higher versions +# require Python 3.11+ and we want to maintain Python 3.10 compatibility. +jax<=0.5 +contourpy<=1.3.2 +networkx<=3.4 diff --git a/requirements.txt b/requirements.txt index ac86eb121..b6c333b04 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,27 +1,17 @@ # -# This file is autogenerated by pip-compile with Python 3.11 +# This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --allow-unsafe --no-strip-extras +# ./scripts/generate_requirements.sh # - -absl-py==2.1.0 +absl-py==2.3.1 # via # keras # tensorboard # tensorflow - # tensorflow-docs -astor==0.8.1 - # via tensorflow-docs -astroid==3.3.11 - # via pylint astunparse==1.6.3 # via tensorflow -attrs==25.4.0 - # via - # jsonschema - # referencing -cachetools==6.2.2 +cachetools==6.2.3 # via google-auth certifi==2025.11.12 # via requests @@ -34,18 +24,20 @@ cirq-core==1.3.0 cirq-google==1.3.0 # via -r requirements.in contourpy==1.3.2 - # via matplotlib + # via + # -r requirements.in + # matplotlib cycler==0.12.1 # via matplotlib -dill==0.4.0 - # via pylint duet==0.2.9 # via cirq-core flatbuffers==25.9.23 # via tensorflow -fonttools==4.60.1 - # via matplotlib -gast==0.6.0 +fonttools==4.61.1 + # via + # -c requirements-pins.txt + # matplotlib +gast==0.7.0 # via tensorflow google-api-core[grpc]==2.28.1 # via cirq-google @@ -57,13 +49,13 @@ googleapis-common-protos==1.72.0 # via # google-api-core # grpcio-status -grpcio==1.60.2 +grpcio==1.76.0 # via # google-api-core # grpcio-status # tensorboard # tensorflow -grpcio-status==1.60.2 +grpcio-status==1.62.3 # via google-api-core h5py==3.15.1 # via @@ -71,22 +63,10 @@ h5py==3.15.1 # tensorflow idna==3.11 # via requests -ipython-genutils==0.2.0 - # via nbformat -isort==5.13.2 - # via pylint -jinja2==3.1.6 - # via tensorflow-docs -jsonschema==4.25.1 - # via nbformat -jsonschema-specifications==2025.9.1 - # via jsonschema -jupyter-client==8.6.3 - # via nbclient -jupyter-core==5.9.1 - # via - # jupyter-client - # nbformat +jax==0.4.34 + # via -r requirements.in +jaxlib==0.4.34 + # via jax keras==3.12.0 # via tensorflow kiwisolver==1.4.9 @@ -98,39 +78,33 @@ markdown==3.10 markdown-it-py==4.0.0 # via rich markupsafe==3.0.3 - # via - # jinja2 - # werkzeug -matplotlib==3.10.7 + # via werkzeug +matplotlib==3.10.8 # via cirq-core -mccabe==0.7.0 - # via pylint mdurl==0.1.2 # via markdown-it-py ml-dtypes==0.3.2 # via + # jax + # jaxlib # keras # tensorflow mpmath==1.3.0 # via sympy namex==0.1.0 # via keras -nbclient==0.6.5 - # via -r requirements.in -nbformat==5.1.3 +networkx==3.4 # via # -r requirements.in - # nbclient - # tensorflow-docs -nest-asyncio==1.6.0 - # via nbclient -networkx==3.4.2 - # via cirq-core + # cirq-core numpy==1.26.4 # via + # -r requirements.in # cirq-core # contourpy # h5py + # jax + # jaxlib # keras # matplotlib # ml-dtypes @@ -139,7 +113,9 @@ numpy==1.26.4 # tensorboard # tensorflow opt-einsum==3.4.0 - # via tensorflow + # via + # jax + # tensorflow optree==0.18.0 # via keras packaging==25.0 @@ -147,15 +123,11 @@ packaging==25.0 # keras # matplotlib # tensorflow + # wheel pandas==2.3.3 # via cirq-core pillow==12.0.0 # via matplotlib -platformdirs==4.5.0 - # via - # jupyter-core - # pylint - # yapf proto-plus==1.26.1 # via # cirq-google @@ -169,7 +141,6 @@ protobuf==4.25.8 # proto-plus # tensorboard # tensorflow - # tensorflow-docs pyasn1==0.6.1 # via # pyasn1-modules @@ -178,39 +149,28 @@ pyasn1-modules==0.4.2 # via google-auth pygments==2.19.2 # via rich -pylint==3.3.3 - # via -r requirements.in pyparsing==3.2.5 # via matplotlib python-dateutil==2.9.0.post0 # via - # jupyter-client # matplotlib # pandas pytz==2025.2 # via pandas -pyyaml - # via tensorflow-docs -pyzmq==27.1.0 - # via jupyter-client -referencing==0.37.0 - # via - # jsonschema - # jsonschema-specifications requests==2.32.5 # via # google-api-core # tensorflow rich==14.2.0 # via keras -rpds-py==0.29.0 - # via - # jsonschema - # referencing rsa==4.9.1 # via google-auth -scipy==1.15.3 - # via cirq-core +scipy==1.12.0 + # via + # -r requirements.in + # cirq-core + # jax + # jaxlib six==1.17.0 # via # astunparse @@ -221,7 +181,9 @@ six==1.17.0 sortedcontainers==2.4.0 # via cirq-core sympy==1.14.0 - # via cirq-core + # via + # -r requirements.in + # cirq-core tensorboard==2.16.2 # via tensorflow tensorboard-data-server==0.7.2 @@ -230,47 +192,38 @@ tensorflow==2.16.2 # via # -r requirements.in # tf-keras -tensorflow-docs==2025.2.19.33219 - # via -r requirements.in tensorflow-io-gcs-filesystem==0.37.1 # via tensorflow termcolor==3.2.0 # via tensorflow tf-keras==2.16.0 # via -r requirements.in -tomlkit==0.13.3 - # via pylint -tornado==6.5.2 - # via jupyter-client tqdm==4.67.1 # via cirq-core -traitlets==5.14.3 - # via - # jupyter-client - # jupyter-core - # nbclient - # nbformat typing-extensions==4.15.0 # via # cirq-core + # grpcio # optree - # referencing # tensorflow -tzdata==2025.2 +tzdata==2025.3 # via pandas -urllib3==2.5.0 - # via requests -werkzeug==3.1.3 - # via tensorboard -wheel==0.45.1 +urllib3==2.6.2 + # via + # -c requirements-pins.txt + # requests +werkzeug==3.1.4 + # via + # -c requirements-pins.txt + # tensorboard +wheel==0.46.1 # via astunparse -wrapt==1.17.3 +wrapt==2.0.1 # via tensorflow -yapf==0.43.0 - # via -r requirements.in # The following packages are considered to be unsafe in a requirements file: setuptools==68.2.2 # via + # -r requirements.in # tensorboard # tensorflow diff --git a/scripts/generate_requirements.sh b/scripts/generate_requirements.sh index 8868273e7..bc8da9f23 100755 --- a/scripts/generate_requirements.sh +++ b/scripts/generate_requirements.sh @@ -15,29 +15,36 @@ # ============================================================================== # Summary: produce requirements.txt using pip-compile & munging the result. -# Usage: ./generate_requirements.sh +# Usage: ./scripts/generate_requirements.sh from the top dir of the repo. set -eu # Find the top of the local TFQ git tree. Do it early in case this fails. -thisdir=$(CDPATH="" cd -- "$(dirname -- "$0")" && pwd -P) +thisdir=$(CDPATH="" cd -- "$(dirname -- "${0}")" && pwd -P) repo_dir=$(git -C "${thisdir}" rev-parse --show-toplevel 2>/dev/null || \ echo "${thisdir}/..") -echo "Running pip-compile in ${repo_dir} …" -pip-compile -q --no-strip-extras --allow-unsafe +# Ensure we have pip-compile. +if ! pip show -qq pip-tools; then + echo "Python pip-tools not found. Please run 'pip install pip-tools'." + exit 1 +fi -declare -a inplace_edit=(-i) -if [[ "$(uname -s)" == "Darwin" ]]; then - # macOS uses BSD sed, which requires a suffix for -i. - inplace_edit+=('') +declare -a constraint=() +pins_file="$(realpath --relative-to=. "${repo_dir}/requirements-pins.txt")" +if [[ -e "${pins_file}" ]]; then + constraint+=(--constraint "${pins_file}") fi -echo "Adjusting output of pip-compile …" -sed "${inplace_edit[@]}" \ - -e '/^--index-url/d' \ - -e '/^--extra-index-url/d' \ - -e 's/^pyyaml==.*/pyyaml/' \ - requirements.txt +# Tell pip-compile to reference this script in the requirements.txt comments. +export CUSTOM_COMPILE_COMMAND="${0}" + +echo "Running pip-compile in ${repo_dir} …" +pip-compile -q \ + --rebuild \ + --allow-unsafe \ + --no-strip-extras \ + --no-emit-index-url \ + "${constraint[@]}" echo "Done." diff --git a/tensorflow_quantum/core/ops/math_ops/fidelity_op.py b/tensorflow_quantum/core/ops/math_ops/fidelity_op.py index 8f2e87e44..9e704794d 100644 --- a/tensorflow_quantum/core/ops/math_ops/fidelity_op.py +++ b/tensorflow_quantum/core/ops/math_ops/fidelity_op.py @@ -25,9 +25,11 @@ def fidelity(programs, symbol_names, symbol_values, other_programs): Compute (potentially many) fidelities between the given circuits and the symbol free comparison circuits. - Calculates out[i][j] = $ | \langle \psi_{\text{programs[i]}} \\ - (\text{symbol\_values[i]}) | \psi_{\text{other\_programs[j]}} \rangle \\ - |^2 $ + Calculates out[i][j] as: + $$ + |\langle \psi_{\text{programs[i]}}(\text{symbol_values[i]}) \mid + \psi_{\text{other_programs[j]}} \rangle|^2 + $$ >>> symbols = sympy.symbols('alpha beta') diff --git a/tensorflow_quantum/core/ops/math_ops/inner_product_op.py b/tensorflow_quantum/core/ops/math_ops/inner_product_op.py index 5d92b7b92..18529ba18 100644 --- a/tensorflow_quantum/core/ops/math_ops/inner_product_op.py +++ b/tensorflow_quantum/core/ops/math_ops/inner_product_op.py @@ -75,8 +75,11 @@ def inner_product(programs, symbol_names, symbol_values, other_programs): Compute (potentially many) inner products between the given circuits and the symbol free comparison circuits. - Calculates out[i][j] = $ \langle \psi_{\text{programs[i]}} \\ - (\text{symbol\_values[i]}) | \psi_{\text{other\_programs[j]}} \rangle $ + Calculates out[i][j] as: + $$ + \langle \psi_{\text{programs[i]}}(\text{symbol_values[i]}) \mid + \psi_{\text{other_programs[j]}} \rangle + $$ >>> symbols = sympy.symbols('alpha beta')