diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 5323633bc27..0f462d9a49d 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -347,3 +347,59 @@ jobs: cd tmp-${{ matrix.framework }} flwr build flwr install *.fab + + numpy: + runs-on: ubuntu-22.04 + timeout-minutes: 10 + needs: wheel + strategy: + fail-fast: false + matrix: + numpy-version: ["1.26"] + python-version: ["3.11"] + directory: [e2e-bare-auth] + connection: [insecure] + engine: [deployment-engine, simulation-engine] + authentication: [no-auth] + name: | + NumPy ${{ matrix.numpy-version }} / + Python ${{ matrix.python-version }} / + ${{ matrix.connection }} / + ${{ matrix.authentication }} / + ${{ matrix.engine }} + defaults: + run: + working-directory: e2e/${{ matrix.directory }} + steps: + - uses: actions/checkout@v4 + - name: Bootstrap + uses: ./.github/actions/bootstrap + with: + python-version: ${{ matrix.python-version }} + poetry-skip: 'true' + - name: Install Flower from repo + if: ${{ github.repository != 'adap/flower' || github.event.pull_request.head.repo.fork || github.actor == 'dependabot[bot]' }} + working-directory: ./ + run: | + if [[ "${{ matrix.engine }}" == "simulation-engine" ]]; then + python -m pip install ".[simulation]" "numpy>=${{ matrix.numpy-version }},<2.0" + else + python -m pip install . "numpy>=${{ matrix.numpy-version }},<2.0" + fi + - name: Download and install Flower wheel from artifact store + if: ${{ github.repository == 'adap/flower' && !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' }} + run: | + # Define base URL for wheel file + WHEEL_URL="https://${{ env.ARTIFACT_BUCKET }}/py/${{ needs.wheel.outputs.dir }}/${{ needs.wheel.outputs.short_sha }}/${{ needs.wheel.outputs.whl_path }}" + if [[ "${{ matrix.engine }}" == "simulation-engine" ]]; then + python -m pip install "flwr[simulation] @ ${WHEEL_URL}" "numpy>=${{ matrix.numpy-version }},<2.0" + else + python -m pip install "${WHEEL_URL}" "numpy>=${{ matrix.numpy-version }},<2.0" + fi + - name: > + Run Flower - NumPy 1.26 test / + ${{ matrix.connection }} / + ${{ matrix.authentication }} / + ${{ matrix.engine }} + working-directory: e2e/${{ matrix.directory }} + run: ./../test_exec_api.sh "${{ matrix.connection }}" "${{ matrix.authentication}}" "${{ matrix.engine }}" diff --git a/datasets/e2e/pytorch/pyproject.toml b/datasets/e2e/pytorch/pyproject.toml index 3f1f12d5f4b..d42409ca119 100644 --- a/datasets/e2e/pytorch/pyproject.toml +++ b/datasets/e2e/pytorch/pyproject.toml @@ -11,6 +11,6 @@ authors = ["The Flower Authors "] [tool.poetry.dependencies] python = "^3.9" flwr-datasets = { path = "./../../", extras = ["vision"] } -torch = "^1.12.0" -torchvision = "^0.14.1" +torch = ">=1.12.0,<3.0.0" +torchvision = ">=0.19.0,<1.0.0" parameterized = "==0.9.0" diff --git a/datasets/flwr_datasets/common/typing.py b/datasets/flwr_datasets/common/typing.py index d6d37b46849..6b76e7b22ee 100644 --- a/datasets/flwr_datasets/common/typing.py +++ b/datasets/flwr_datasets/common/typing.py @@ -22,5 +22,5 @@ NDArray = npt.NDArray[Any] NDArrayInt = npt.NDArray[np.int_] -NDArrayFloat = npt.NDArray[np.float_] +NDArrayFloat = npt.NDArray[np.float64] NDArrays = list[NDArray] diff --git a/datasets/flwr_datasets/partitioner/dirichlet_partitioner_test.py b/datasets/flwr_datasets/partitioner/dirichlet_partitioner_test.py index ed38e8ee2a4..693e0d6a5aa 100644 --- a/datasets/flwr_datasets/partitioner/dirichlet_partitioner_test.py +++ b/datasets/flwr_datasets/partitioner/dirichlet_partitioner_test.py @@ -29,7 +29,7 @@ def _dummy_setup( num_partitions: int, - alpha: Union[float, NDArray[np.float_]], + alpha: Union[float, NDArray[np.float64]], num_rows: int, partition_by: str, self_balancing: bool = True, diff --git a/datasets/pyproject.toml b/datasets/pyproject.toml index af7c1f1bde2..d1cd7ab7868 100644 --- a/datasets/pyproject.toml +++ b/datasets/pyproject.toml @@ -52,7 +52,7 @@ exclude = [ [tool.poetry.dependencies] python = "^3.9" -numpy = "^1.21.0" +numpy = ">=1.26.0,<3.0.0" datasets = ">=2.14.6 <=3.1.0" pillow = { version = ">=6.2.1", optional = true } soundfile = { version = ">=0.12.1", optional = true } diff --git a/e2e/e2e-pandas/pyproject.toml b/e2e/e2e-pandas/pyproject.toml index f10b05b4475..120e9b8e6d3 100644 --- a/e2e/e2e-pandas/pyproject.toml +++ b/e2e/e2e-pandas/pyproject.toml @@ -11,7 +11,7 @@ authors = [{ name = "Ragy Haddad", email = "ragy202@gmail.com" }] maintainers = [{ name = "The Flower Authors", email = "hello@flower.ai" }] dependencies = [ "flwr[simulation] @ {root:parent:parent:uri}", - "numpy>=1.21.0,<2.0.0", + "numpy>=2.0.0", "pandas>=2.0.0,<3.0.0", "scikit-learn>=1.1.1,<2.0.0", ] diff --git a/e2e/e2e-pytorch-lightning/pyproject.toml b/e2e/e2e-pytorch-lightning/pyproject.toml index 66ecbb6296d..efb0eb1bebf 100644 --- a/e2e/e2e-pytorch-lightning/pyproject.toml +++ b/e2e/e2e-pytorch-lightning/pyproject.toml @@ -9,8 +9,8 @@ description = "Federated Learning E2E test with Flower and PyTorch Lightning" license = "Apache-2.0" dependencies = [ "flwr[simulation] @ {root:parent:parent:uri}", - "pytorch-lightning==2.2.4", - "torchvision==0.14.1", + "pytorch-lightning==2.4.0", + "torchvision>=0.20.1,<0.21.0", ] [tool.hatch.build.targets.wheel] diff --git a/e2e/e2e-pytorch/pyproject.toml b/e2e/e2e-pytorch/pyproject.toml index 0e48334693d..9e2029aecef 100644 --- a/e2e/e2e-pytorch/pyproject.toml +++ b/e2e/e2e-pytorch/pyproject.toml @@ -9,8 +9,8 @@ description = "PyTorch Federated Learning E2E test with Flower" license = "Apache-2.0" dependencies = [ "flwr[simulation] @ {root:parent:parent:uri}", - "torch>=1.12.0,<2.0.0", - "torchvision>=0.14.1,<0.15.0", + "torch>=2.5.0,<3.0.0", + "torchvision>=0.20.1,<0.21.0", "tqdm>=4.63.0,<5.0.0", ] diff --git a/e2e/e2e-scikit-learn/pyproject.toml b/e2e/e2e-scikit-learn/pyproject.toml index aef9a4a8a00..03f5540aa15 100644 --- a/e2e/e2e-scikit-learn/pyproject.toml +++ b/e2e/e2e-scikit-learn/pyproject.toml @@ -15,6 +15,7 @@ dependencies = [ "flwr[simulation,rest] @ {root:parent:parent:uri}", "scikit-learn>=1.1.1,<2.0.0", "openml>=0.14.0,<0.15.0", + "numpy<2.0.0", ] [tool.hatch.build.targets.wheel] diff --git a/examples/custom-mods/pyproject.toml b/examples/custom-mods/pyproject.toml index ff36398ef15..429a7c2f1b9 100644 --- a/examples/custom-mods/pyproject.toml +++ b/examples/custom-mods/pyproject.toml @@ -11,7 +11,7 @@ authors = ["The Flower Authors "] [tool.poetry.dependencies] python = ">=3.9,<3.11" flwr = { path = "../../", develop = true, extras = ["simulation"] } -tensorboard = "2.16.2" +tensorboard = "2.18.0" torch = "1.13.1" torchvision = "0.14.1" tqdm = "4.65.0" diff --git a/examples/sklearn-logreg-mnist/pyproject.toml b/examples/sklearn-logreg-mnist/pyproject.toml index 75dae57a0a4..73e089eb62d 100644 --- a/examples/sklearn-logreg-mnist/pyproject.toml +++ b/examples/sklearn-logreg-mnist/pyproject.toml @@ -14,7 +14,7 @@ authors = [ dependencies = [ "flwr[simulation]>=1.12.0", "flwr-datasets[vision]>=0.3.0", - "numpy<2.0.0", + "numpy>=2.0.0", "scikit-learn~=1.2.2", ] diff --git a/pyproject.toml b/pyproject.toml index 2b789fc3d62..f6ffa3dbada 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,7 @@ flower-client-app = "flwr.client.supernode:run_client_app" # Deprecated [tool.poetry.dependencies] python = "^3.9" # Mandatory dependencies -numpy = "^1.21.0" +numpy = ">=1.26.0,<3.0.0" grpcio = "^1.60.0,!=1.64.2,!=1.65.1,!=1.65.2,!=1.65.4,!=1.65.5,!=1.66.0,!=1.66.1" protobuf = "^4.25.2" cryptography = "^42.0.4" diff --git a/src/py/flwr/common/typing.py b/src/py/flwr/common/typing.py index 6b07fe2c1c3..ec8e092548f 100644 --- a/src/py/flwr/common/typing.py +++ b/src/py/flwr/common/typing.py @@ -24,7 +24,7 @@ NDArray = npt.NDArray[Any] NDArrayInt = npt.NDArray[np.int_] -NDArrayFloat = npt.NDArray[np.float_] +NDArrayFloat = npt.NDArray[np.float64] NDArrays = list[NDArray] # The following union type contains Python types corresponding to ProtoBuf types that diff --git a/src/py/flwr/server/strategy/aggregate.py b/src/py/flwr/server/strategy/aggregate.py index 94beacba008..16a6c1faba9 100644 --- a/src/py/flwr/server/strategy/aggregate.py +++ b/src/py/flwr/server/strategy/aggregate.py @@ -48,12 +48,12 @@ def aggregate_inplace(results: list[tuple[ClientProxy, FitRes]]) -> NDArrays: num_examples_total = sum(fit_res.num_examples for (_, fit_res) in results) # Compute scaling factors for each result - scaling_factors = [ - fit_res.num_examples / num_examples_total for _, fit_res in results - ] + scaling_factors = np.asarray( + [fit_res.num_examples / num_examples_total for _, fit_res in results] + ) def _try_inplace( - x: NDArray, y: Union[NDArray, float], np_binary_op: np.ufunc + x: NDArray, y: Union[NDArray, np.float64], np_binary_op: np.ufunc ) -> NDArray: return ( # type: ignore[no-any-return] np_binary_op(x, y, out=x)