flwr-nightly 1.8.0.dev20240226__tar.gz → 1.8.0.dev20240227__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/PKG-INFO +1 -1
  2. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/pyproject.toml +1 -1
  3. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/__init__.py +1 -1
  4. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/app.py +4 -3
  5. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/mod/__init__.py +2 -0
  6. flwr_nightly-1.8.0.dev20240227/src/py/flwr/client/mod/centraldp_mods.py +76 -0
  7. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/differential_privacy_constants.py +2 -0
  8. flwr_nightly-1.8.0.dev20240227/src/py/flwr/common/exit_handlers.py +87 -0
  9. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/app.py +7 -54
  10. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/__init__.py +5 -1
  11. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/dp_fixed_clipping.py +156 -2
  12. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/vce/backend/backend.py +1 -1
  13. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +31 -14
  14. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/vce/vce_api.py +1 -1
  15. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/simulation/ray_transport/ray_actor.py +4 -1
  16. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +1 -1
  17. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/LICENSE +0 -0
  18. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/README.md +0 -0
  19. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/__init__.py +0 -0
  20. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/__init__.py +0 -0
  21. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/app.py +0 -0
  22. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/example.py +0 -0
  23. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/__init__.py +0 -0
  24. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/new.py +0 -0
  25. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/__init__.py +0 -0
  26. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/README.md.tpl +0 -0
  27. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/__init__.py +0 -0
  28. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
  29. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
  30. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -0
  31. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
  32. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -0
  33. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
  34. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/flower.toml.tpl +0 -0
  35. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/requirements.pytorch.txt.tpl +0 -0
  36. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/new/templates/app/requirements.tensorflow.txt.tpl +0 -0
  37. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/cli/utils.py +0 -0
  38. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/client.py +0 -0
  39. /flwr_nightly-1.8.0.dev20240226/src/py/flwr/client/clientapp.py → /flwr_nightly-1.8.0.dev20240227/src/py/flwr/client/client_app.py +0 -0
  40. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/dpfedavg_numpy_client.py +0 -0
  41. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/grpc_client/__init__.py +0 -0
  42. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/grpc_client/connection.py +0 -0
  43. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/grpc_rere_client/__init__.py +0 -0
  44. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/grpc_rere_client/connection.py +0 -0
  45. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/message_handler/__init__.py +0 -0
  46. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/message_handler/message_handler.py +0 -0
  47. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/message_handler/task_handler.py +0 -0
  48. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
  49. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
  50. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/mod/utils.py +0 -0
  51. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/node_state.py +0 -0
  52. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/node_state_tests.py +0 -0
  53. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/numpy_client.py +0 -0
  54. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/rest_client/__init__.py +0 -0
  55. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/rest_client/connection.py +0 -0
  56. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/client/typing.py +0 -0
  57. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/__init__.py +0 -0
  58. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/address.py +0 -0
  59. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/constant.py +0 -0
  60. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/context.py +0 -0
  61. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/date.py +0 -0
  62. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/differential_privacy.py +0 -0
  63. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/dp.py +0 -0
  64. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/grpc.py +0 -0
  65. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/logger.py +0 -0
  66. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/message.py +0 -0
  67. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/parameter.py +0 -0
  68. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/record/__init__.py +0 -0
  69. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/record/configsrecord.py +0 -0
  70. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/record/conversion_utils.py +0 -0
  71. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/record/metricsrecord.py +0 -0
  72. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/record/parametersrecord.py +0 -0
  73. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/record/recordset.py +0 -0
  74. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/record/typeddict.py +0 -0
  75. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/recordset_compat.py +0 -0
  76. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/retry_invoker.py +0 -0
  77. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/secure_aggregation/__init__.py +0 -0
  78. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
  79. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
  80. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +0 -0
  81. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
  82. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/secure_aggregation/quantization.py +0 -0
  83. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
  84. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
  85. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/serde.py +0 -0
  86. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/telemetry.py +0 -0
  87. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/typing.py +0 -0
  88. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/common/version.py +0 -0
  89. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/__init__.py +0 -0
  90. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/driver_pb2.py +0 -0
  91. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/driver_pb2.pyi +0 -0
  92. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/driver_pb2_grpc.py +0 -0
  93. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/driver_pb2_grpc.pyi +0 -0
  94. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/fleet_pb2.py +0 -0
  95. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/fleet_pb2.pyi +0 -0
  96. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/fleet_pb2_grpc.py +0 -0
  97. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/fleet_pb2_grpc.pyi +0 -0
  98. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/node_pb2.py +0 -0
  99. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/node_pb2.pyi +0 -0
  100. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/node_pb2_grpc.py +0 -0
  101. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/node_pb2_grpc.pyi +0 -0
  102. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/recordset_pb2.py +0 -0
  103. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/recordset_pb2.pyi +0 -0
  104. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/recordset_pb2_grpc.py +0 -0
  105. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/recordset_pb2_grpc.pyi +0 -0
  106. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/task_pb2.py +0 -0
  107. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/task_pb2.pyi +0 -0
  108. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/task_pb2_grpc.py +0 -0
  109. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/task_pb2_grpc.pyi +0 -0
  110. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/transport_pb2.py +0 -0
  111. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/transport_pb2.pyi +0 -0
  112. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/transport_pb2_grpc.py +0 -0
  113. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
  114. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/py.typed +0 -0
  115. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/__init__.py +0 -0
  116. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/client_manager.py +0 -0
  117. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/client_proxy.py +0 -0
  118. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/compat/__init__.py +0 -0
  119. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/compat/app.py +0 -0
  120. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/compat/driver_client_proxy.py +0 -0
  121. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/criterion.py +0 -0
  122. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/driver/__init__.py +0 -0
  123. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/driver/driver.py +0 -0
  124. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/driver/grpc_driver.py +0 -0
  125. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/history.py +0 -0
  126. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/run_serverapp.py +0 -0
  127. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/server.py +0 -0
  128. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/server_app.py +0 -0
  129. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/server_config.py +0 -0
  130. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/aggregate.py +0 -0
  131. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/bulyan.py +0 -0
  132. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
  133. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
  134. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
  135. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedadagrad.py +0 -0
  136. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedadam.py +0 -0
  137. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedavg.py +0 -0
  138. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedavg_android.py +0 -0
  139. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedavgm.py +0 -0
  140. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedmedian.py +0 -0
  141. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedopt.py +0 -0
  142. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedprox.py +0 -0
  143. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
  144. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
  145. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
  146. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
  147. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/fedyogi.py +0 -0
  148. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/krum.py +0 -0
  149. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/qfedavg.py +0 -0
  150. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/strategy/strategy.py +0 -0
  151. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/__init__.py +0 -0
  152. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/driver/__init__.py +0 -0
  153. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/driver/driver_servicer.py +0 -0
  154. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/__init__.py +0 -0
  155. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
  156. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
  157. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
  158. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
  159. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +0 -0
  160. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
  161. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +0 -0
  162. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
  163. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +0 -0
  164. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
  165. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +0 -0
  166. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
  167. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
  168. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/state/__init__.py +0 -0
  169. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/state/in_memory_state.py +0 -0
  170. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/state/sqlite_state.py +0 -0
  171. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/state/state.py +0 -0
  172. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/superlink/state/state_factory.py +0 -0
  173. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/typing.py +0 -0
  174. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/utils/__init__.py +0 -0
  175. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/utils/tensorboard.py +0 -0
  176. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/server/utils/validator.py +0 -0
  177. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/simulation/__init__.py +0 -0
  178. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/simulation/app.py +0 -0
  179. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/simulation/ray_transport/__init__.py +0 -0
  180. {flwr_nightly-1.8.0.dev20240226 → flwr_nightly-1.8.0.dev20240227}/src/py/flwr/simulation/ray_transport/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flwr-nightly
3
- Version: 1.8.0.dev20240226
3
+ Version: 1.8.0.dev20240227
4
4
  Summary: Flower: A Friendly Federated Learning Framework
5
5
  Home-page: https://flower.ai
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "flwr-nightly"
7
- version = "1.8.0-dev20240226"
7
+ version = "1.8.0-dev20240227"
8
8
  description = "Flower: A Friendly Federated Learning Framework"
9
9
  license = "Apache-2.0"
10
10
  authors = ["The Flower Authors <hello@flower.ai>"]
@@ -19,7 +19,7 @@ from .app import run_client_app as run_client_app
19
19
  from .app import start_client as start_client
20
20
  from .app import start_numpy_client as start_numpy_client
21
21
  from .client import Client as Client
22
- from .clientapp import ClientApp as ClientApp
22
+ from .client_app import ClientApp as ClientApp
23
23
  from .numpy_client import NumPyClient as NumPyClient
24
24
  from .typing import ClientFn as ClientFn
25
25
 
@@ -23,7 +23,7 @@ from pathlib import Path
23
23
  from typing import Callable, ContextManager, Optional, Tuple, Union
24
24
 
25
25
  from flwr.client.client import Client
26
- from flwr.client.clientapp import ClientApp
26
+ from flwr.client.client_app import ClientApp
27
27
  from flwr.client.typing import ClientFn
28
28
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH, EventType, Message, event
29
29
  from flwr.common.address import parse_address
@@ -34,9 +34,10 @@ from flwr.common.constant import (
34
34
  TRANSPORT_TYPE_REST,
35
35
  TRANSPORT_TYPES,
36
36
  )
37
+ from flwr.common.exit_handlers import register_exit_handlers
37
38
  from flwr.common.logger import log, warn_deprecated_feature, warn_experimental_feature
38
39
 
39
- from .clientapp import load_client_app
40
+ from .client_app import load_client_app
40
41
  from .grpc_client.connection import grpc_connection
41
42
  from .grpc_rere_client.connection import grpc_request_response
42
43
  from .message_handler.message_handler import handle_control_message
@@ -104,7 +105,7 @@ def run_client_app() -> None:
104
105
  root_certificates=root_certificates,
105
106
  insecure=args.insecure,
106
107
  )
107
- event(EventType.RUN_CLIENT_APP_LEAVE)
108
+ register_exit_handlers(event_type=EventType.RUN_CLIENT_APP_LEAVE)
108
109
 
109
110
 
110
111
  def _parse_args_run_client_app() -> argparse.ArgumentParser:
@@ -15,10 +15,12 @@
15
15
  """Mods."""
16
16
 
17
17
 
18
+ from .centraldp_mods import fixedclipping_mod
18
19
  from .secure_aggregation.secaggplus_mod import secaggplus_mod
19
20
  from .utils import make_ffn
20
21
 
21
22
  __all__ = [
22
23
  "make_ffn",
23
24
  "secaggplus_mod",
25
+ "fixedclipping_mod",
24
26
  ]
@@ -0,0 +1,76 @@
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Clipping modifiers for central DP with client-side clipping."""
16
+
17
+
18
+ from flwr.client.typing import ClientAppCallable
19
+ from flwr.common import ndarrays_to_parameters, parameters_to_ndarrays
20
+ from flwr.common import recordset_compat as compat
21
+ from flwr.common.constant import MESSAGE_TYPE_FIT
22
+ from flwr.common.context import Context
23
+ from flwr.common.differential_privacy import compute_clip_model_update
24
+ from flwr.common.differential_privacy_constants import KEY_CLIPPING_NORM
25
+ from flwr.common.message import Message
26
+
27
+
28
+ def fixedclipping_mod(
29
+ msg: Message, ctxt: Context, call_next: ClientAppCallable
30
+ ) -> Message:
31
+ """Client-side fixed clipping modifier.
32
+
33
+ This mod needs to be used with the DifferentialPrivacyClientSideFixedClipping
34
+ server-side strategy wrapper.
35
+
36
+ The wrapper sends the clipping_norm value to the client.
37
+
38
+ This mod clips the client model updates before sending them to the server.
39
+
40
+ It operates on messages with type MESSAGE_TYPE_FIT.
41
+
42
+ Notes
43
+ -----
44
+ Consider the order of mods when using multiple.
45
+
46
+ Typically, fixedclipping_mod should be the last to operate on params.
47
+ """
48
+ if msg.metadata.message_type != MESSAGE_TYPE_FIT:
49
+ return call_next(msg, ctxt)
50
+ fit_ins = compat.recordset_to_fitins(msg.content, keep_input=True)
51
+ if KEY_CLIPPING_NORM not in fit_ins.config:
52
+ raise KeyError(
53
+ f"The {KEY_CLIPPING_NORM} value is not supplied by the "
54
+ f"DifferentialPrivacyClientSideFixedClipping wrapper at"
55
+ f" the server side."
56
+ )
57
+
58
+ clipping_norm = float(fit_ins.config[KEY_CLIPPING_NORM])
59
+ server_to_client_params = parameters_to_ndarrays(fit_ins.parameters)
60
+
61
+ # Call inner app
62
+ out_msg = call_next(msg, ctxt)
63
+ fit_res = compat.recordset_to_fitres(out_msg.content, keep_input=True)
64
+
65
+ client_to_server_params = parameters_to_ndarrays(fit_res.parameters)
66
+
67
+ # Clip the client update
68
+ compute_clip_model_update(
69
+ client_to_server_params,
70
+ server_to_client_params,
71
+ clipping_norm,
72
+ )
73
+
74
+ fit_res.parameters = ndarrays_to_parameters(client_to_server_params)
75
+ out_msg.content = compat.fitres_to_recordset(fit_res, keep_input=True)
76
+ return out_msg
@@ -14,6 +14,8 @@
14
14
  # ==============================================================================
15
15
  """Constants for differential privacy."""
16
16
 
17
+
18
+ KEY_CLIPPING_NORM = "clipping_norm"
17
19
  CLIENTS_DISCREPANCY_WARNING = (
18
20
  "The number of clients returning parameters (%s)"
19
21
  " differs from the number of sampled clients (%s)."
@@ -0,0 +1,87 @@
1
+ # Copyright 2024 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Common function to register exit handlers for server and client."""
16
+
17
+
18
+ import sys
19
+ from signal import SIGINT, SIGTERM, signal
20
+ from threading import Thread
21
+ from types import FrameType
22
+ from typing import List, Optional
23
+
24
+ from grpc import Server
25
+
26
+ from flwr.common.telemetry import EventType, event
27
+
28
+
29
+ def register_exit_handlers(
30
+ event_type: EventType,
31
+ grpc_servers: Optional[List[Server]] = None,
32
+ bckg_threads: Optional[List[Thread]] = None,
33
+ ) -> None:
34
+ """Register exit handlers for `SIGINT` and `SIGTERM` signals.
35
+
36
+ Parameters
37
+ ----------
38
+ event_type : EventType
39
+ The telemetry event that should be logged before exit.
40
+ grpc_servers: Optional[List[Server]] (default: None)
41
+ An otpional list of gRPC servers that need to be gracefully
42
+ terminated before exiting.
43
+ bckg_threads: Optional[List[Thread]] (default: None)
44
+ An optional list of threads that need to be gracefully
45
+ terminated before exiting.
46
+ """
47
+ default_handlers = {
48
+ SIGINT: None,
49
+ SIGTERM: None,
50
+ }
51
+
52
+ def graceful_exit_handler( # type: ignore
53
+ signalnum,
54
+ frame: FrameType, # pylint: disable=unused-argument
55
+ ) -> None:
56
+ """Exit handler to be registered with `signal.signal`.
57
+
58
+ When called will reset signal handler to original signal handler from
59
+ default_handlers.
60
+ """
61
+ # Reset to default handler
62
+ signal(signalnum, default_handlers[signalnum])
63
+
64
+ event_res = event(event_type=event_type)
65
+
66
+ if grpc_servers is not None:
67
+ for grpc_server in grpc_servers:
68
+ grpc_server.stop(grace=1)
69
+
70
+ if bckg_threads is not None:
71
+ for bckg_thread in bckg_threads:
72
+ bckg_thread.join()
73
+
74
+ # Ensure event has happend
75
+ event_res.result()
76
+
77
+ # Setup things for graceful exit
78
+ sys.exit(0)
79
+
80
+ default_handlers[SIGINT] = signal( # type: ignore
81
+ SIGINT,
82
+ graceful_exit_handler, # type: ignore
83
+ )
84
+ default_handlers[SIGTERM] = signal( # type: ignore
85
+ SIGTERM,
86
+ graceful_exit_handler, # type: ignore
87
+ )
@@ -22,8 +22,6 @@ import threading
22
22
  from logging import ERROR, INFO, WARN
23
23
  from os.path import isfile
24
24
  from pathlib import Path
25
- from signal import SIGINT, SIGTERM, signal
26
- from types import FrameType
27
25
  from typing import List, Optional, Tuple
28
26
 
29
27
  import grpc
@@ -36,6 +34,7 @@ from flwr.common.constant import (
36
34
  TRANSPORT_TYPE_REST,
37
35
  TRANSPORT_TYPE_VCE,
38
36
  )
37
+ from flwr.common.exit_handlers import register_exit_handlers
39
38
  from flwr.common.logger import log
40
39
  from flwr.proto.driver_pb2_grpc import ( # pylint: disable=E0611
41
40
  add_DriverServicer_to_server,
@@ -212,10 +211,10 @@ def run_driver_api() -> None:
212
211
  )
213
212
 
214
213
  # Graceful shutdown
215
- _register_exit_handlers(
214
+ register_exit_handlers(
215
+ event_type=EventType.RUN_DRIVER_API_LEAVE,
216
216
  grpc_servers=[grpc_server],
217
217
  bckg_threads=[],
218
- event_type=EventType.RUN_DRIVER_API_LEAVE,
219
218
  )
220
219
 
221
220
  # Block
@@ -280,10 +279,10 @@ def run_fleet_api() -> None:
280
279
  raise ValueError(f"Unknown fleet_api_type: {args.fleet_api_type}")
281
280
 
282
281
  # Graceful shutdown
283
- _register_exit_handlers(
282
+ register_exit_handlers(
283
+ event_type=EventType.RUN_FLEET_API_LEAVE,
284
284
  grpc_servers=grpc_servers,
285
285
  bckg_threads=bckg_threads,
286
- event_type=EventType.RUN_FLEET_API_LEAVE,
287
286
  )
288
287
 
289
288
  # Block
@@ -375,10 +374,10 @@ def run_superlink() -> None:
375
374
  raise ValueError(f"Unknown fleet_api_type: {args.fleet_api_type}")
376
375
 
377
376
  # Graceful shutdown
378
- _register_exit_handlers(
377
+ register_exit_handlers(
378
+ event_type=EventType.RUN_SUPERLINK_LEAVE,
379
379
  grpc_servers=grpc_servers,
380
380
  bckg_threads=bckg_threads,
381
- event_type=EventType.RUN_SUPERLINK_LEAVE,
382
381
  )
383
382
 
384
383
  # Block
@@ -413,52 +412,6 @@ def _try_obtain_certificates(
413
412
  return certificates
414
413
 
415
414
 
416
- def _register_exit_handlers(
417
- grpc_servers: List[grpc.Server],
418
- bckg_threads: List[threading.Thread],
419
- event_type: EventType,
420
- ) -> None:
421
- default_handlers = {
422
- SIGINT: None,
423
- SIGTERM: None,
424
- }
425
-
426
- def graceful_exit_handler( # type: ignore
427
- signalnum,
428
- frame: FrameType, # pylint: disable=unused-argument
429
- ) -> None:
430
- """Exit handler to be registered with signal.signal.
431
-
432
- When called will reset signal handler to original signal handler from
433
- default_handlers.
434
- """
435
- # Reset to default handler
436
- signal(signalnum, default_handlers[signalnum])
437
-
438
- event_res = event(event_type=event_type)
439
-
440
- for grpc_server in grpc_servers:
441
- grpc_server.stop(grace=1)
442
-
443
- for bckg_thread in bckg_threads:
444
- bckg_thread.join()
445
-
446
- # Ensure event has happend
447
- event_res.result()
448
-
449
- # Setup things for graceful exit
450
- sys.exit(0)
451
-
452
- default_handlers[SIGINT] = signal( # type: ignore
453
- SIGINT,
454
- graceful_exit_handler, # type: ignore
455
- )
456
- default_handlers[SIGTERM] = signal( # type: ignore
457
- SIGTERM,
458
- graceful_exit_handler, # type: ignore
459
- )
460
-
461
-
462
415
  def _run_driver_api_grpc(
463
416
  address: str,
464
417
  state_factory: StateFactory,
@@ -16,7 +16,10 @@
16
16
 
17
17
 
18
18
  from .bulyan import Bulyan as Bulyan
19
- from .dp_fixed_clipping import DifferentialPrivacyServerSideFixedClipping
19
+ from .dp_fixed_clipping import (
20
+ DifferentialPrivacyClientSideFixedClipping,
21
+ DifferentialPrivacyServerSideFixedClipping,
22
+ )
20
23
  from .dpfedavg_adaptive import DPFedAvgAdaptive as DPFedAvgAdaptive
21
24
  from .dpfedavg_fixed import DPFedAvgFixed as DPFedAvgFixed
22
25
  from .fault_tolerant_fedavg import FaultTolerantFedAvg as FaultTolerantFedAvg
@@ -59,4 +62,5 @@ __all__ = [
59
62
  "DPFedAvgFixed",
60
63
  "Strategy",
61
64
  "DifferentialPrivacyServerSideFixedClipping",
65
+ "DifferentialPrivacyClientSideFixedClipping",
62
66
  ]
@@ -36,7 +36,10 @@ from flwr.common.differential_privacy import (
36
36
  add_gaussian_noise_to_params,
37
37
  compute_clip_model_update,
38
38
  )
39
- from flwr.common.differential_privacy_constants import CLIENTS_DISCREPANCY_WARNING
39
+ from flwr.common.differential_privacy_constants import (
40
+ CLIENTS_DISCREPANCY_WARNING,
41
+ KEY_CLIPPING_NORM,
42
+ )
40
43
  from flwr.common.logger import log
41
44
  from flwr.server.client_manager import ClientManager
42
45
  from flwr.server.client_proxy import ClientProxy
@@ -44,7 +47,8 @@ from flwr.server.strategy.strategy import Strategy
44
47
 
45
48
 
46
49
  class DifferentialPrivacyServerSideFixedClipping(Strategy):
47
- """Wrapper for Central DP with Server Side Fixed Clipping.
50
+ """Strategy wrapper for central differential privacy with server-side fixed
51
+ clipping.
48
52
 
49
53
  Parameters
50
54
  ----------
@@ -185,3 +189,153 @@ class DifferentialPrivacyServerSideFixedClipping(Strategy):
185
189
  ) -> Optional[Tuple[float, Dict[str, Scalar]]]:
186
190
  """Evaluate model parameters using an evaluation function from the strategy."""
187
191
  return self.strategy.evaluate(server_round, parameters)
192
+
193
+
194
+ class DifferentialPrivacyClientSideFixedClipping(Strategy):
195
+ """Strategy wrapper for central differential privacy with client-side fixed
196
+ clipping.
197
+
198
+ Use `fixedclipping_mod` modifier at the client side.
199
+
200
+ In comparison to `DifferentialPrivacyServerSideFixedClipping`,
201
+ which performs clipping on the server-side, `DifferentialPrivacyClientSideFixedClipping`
202
+ expects clipping to happen on the client-side, usually by using the built-in
203
+ `fixedclipping_mod `.
204
+
205
+ Parameters
206
+ ----------
207
+ strategy : Strategy
208
+ The strategy to which DP functionalities will be added by this wrapper.
209
+ noise_multiplier : float
210
+ The noise multiplier for the Gaussian mechanism for model updates.
211
+ A value of 1.0 or higher is recommended for strong privacy.
212
+ clipping_norm : float
213
+ The value of the clipping norm.
214
+ num_sampled_clients : int
215
+ The number of clients that are sampled on each round.
216
+
217
+ Examples
218
+ --------
219
+ Create a strategy:
220
+
221
+ >>> strategy = fl.server.strategy.FedAvg(...)
222
+
223
+ Wrap the strategy with the `DifferentialPrivacyServerSideFixedClipping` wrapper:
224
+
225
+ >>> DifferentialPrivacyClientSideFixedClipping(
226
+ >>> strategy, cfg.noise_multiplier, cfg.clipping_norm, cfg.num_sampled_clients
227
+ >>> )
228
+
229
+ On the client, add the `fixedclipping_mod` to the client-side mods:
230
+
231
+ >>> app = fl.client.ClientApp(
232
+ >>> client_fn=FlowerClient().to_client(), mods=[fixedclipping_mod]
233
+ >>> )
234
+ """
235
+
236
+ # pylint: disable=too-many-arguments,too-many-instance-attributes
237
+ def __init__(
238
+ self,
239
+ strategy: Strategy,
240
+ noise_multiplier: float,
241
+ clipping_norm: float,
242
+ num_sampled_clients: int,
243
+ ) -> None:
244
+ super().__init__()
245
+
246
+ self.strategy = strategy
247
+
248
+ if noise_multiplier < 0:
249
+ raise ValueError("The noise multiplier should be a non-negative value.")
250
+
251
+ if clipping_norm <= 0:
252
+ raise ValueError("The clipping threshold should be a positive value.")
253
+
254
+ if num_sampled_clients <= 0:
255
+ raise ValueError(
256
+ "The number of sampled clients should be a positive value."
257
+ )
258
+
259
+ self.noise_multiplier = noise_multiplier
260
+ self.clipping_norm = clipping_norm
261
+ self.num_sampled_clients = num_sampled_clients
262
+
263
+ def __repr__(self) -> str:
264
+ """Compute a string representation of the strategy."""
265
+ rep = "Differential Privacy Strategy Wrapper (Client-Side Fixed Clipping)"
266
+ return rep
267
+
268
+ def initialize_parameters(
269
+ self, client_manager: ClientManager
270
+ ) -> Optional[Parameters]:
271
+ """Initialize global model parameters using given strategy."""
272
+ return self.strategy.initialize_parameters(client_manager)
273
+
274
+ def configure_fit(
275
+ self, server_round: int, parameters: Parameters, client_manager: ClientManager
276
+ ) -> List[Tuple[ClientProxy, FitIns]]:
277
+ """Configure the next round of training."""
278
+ additional_config = {KEY_CLIPPING_NORM: self.clipping_norm}
279
+ inner_strategy_config_result = self.strategy.configure_fit(
280
+ server_round, parameters, client_manager
281
+ )
282
+ for _, fit_ins in inner_strategy_config_result:
283
+ fit_ins.config.update(additional_config)
284
+
285
+ return inner_strategy_config_result
286
+
287
+ def configure_evaluate(
288
+ self, server_round: int, parameters: Parameters, client_manager: ClientManager
289
+ ) -> List[Tuple[ClientProxy, EvaluateIns]]:
290
+ """Configure the next round of evaluation."""
291
+ return self.strategy.configure_evaluate(
292
+ server_round, parameters, client_manager
293
+ )
294
+
295
+ def aggregate_fit(
296
+ self,
297
+ server_round: int,
298
+ results: List[Tuple[ClientProxy, FitRes]],
299
+ failures: List[Union[Tuple[ClientProxy, FitRes], BaseException]],
300
+ ) -> Tuple[Optional[Parameters], Dict[str, Scalar]]:
301
+ """Add noise to the aggregated parameters."""
302
+ if failures:
303
+ return None, {}
304
+
305
+ if len(results) != self.num_sampled_clients:
306
+ log(
307
+ WARNING,
308
+ CLIENTS_DISCREPANCY_WARNING,
309
+ len(results),
310
+ self.num_sampled_clients,
311
+ )
312
+
313
+ # Pass the new parameters for aggregation
314
+ aggregated_params, metrics = self.strategy.aggregate_fit(
315
+ server_round, results, failures
316
+ )
317
+
318
+ # Add Gaussian noise to the aggregated parameters
319
+ if aggregated_params:
320
+ aggregated_params = add_gaussian_noise_to_params(
321
+ aggregated_params,
322
+ self.noise_multiplier,
323
+ self.clipping_norm,
324
+ self.num_sampled_clients,
325
+ )
326
+ return aggregated_params, metrics
327
+
328
+ def aggregate_evaluate(
329
+ self,
330
+ server_round: int,
331
+ results: List[Tuple[ClientProxy, EvaluateRes]],
332
+ failures: List[Union[Tuple[ClientProxy, EvaluateRes], BaseException]],
333
+ ) -> Tuple[Optional[float], Dict[str, Scalar]]:
334
+ """Aggregate evaluation losses using the given strategy."""
335
+ return self.strategy.aggregate_evaluate(server_round, results, failures)
336
+
337
+ def evaluate(
338
+ self, server_round: int, parameters: Parameters
339
+ ) -> Optional[Tuple[float, Dict[str, Scalar]]]:
340
+ """Evaluate model parameters using an evaluation function from the strategy."""
341
+ return self.strategy.evaluate(server_round, parameters)
@@ -18,7 +18,7 @@
18
18
  from abc import ABC, abstractmethod
19
19
  from typing import Callable, Dict, Tuple
20
20
 
21
- from flwr.client.clientapp import ClientApp
21
+ from flwr.client.client_app import ClientApp
22
22
  from flwr.common.context import Context
23
23
  from flwr.common.message import Message
24
24
  from flwr.common.typing import ConfigsRecordValues
@@ -15,10 +15,12 @@
15
15
  """Ray backend for the Fleet API using the Simulation Engine."""
16
16
 
17
17
  import pathlib
18
- from logging import INFO
18
+ from logging import ERROR, INFO
19
19
  from typing import Callable, Dict, List, Tuple, Union
20
20
 
21
- from flwr.client.clientapp import ClientApp
21
+ import ray
22
+
23
+ from flwr.client.client_app import ClientApp, LoadClientAppError
22
24
  from flwr.common.context import Context
23
25
  from flwr.common.logger import log
24
26
  from flwr.common.message import Message
@@ -46,6 +48,9 @@ class RayBackend(Backend):
46
48
  log(INFO, "Initialising: %s", self.__class__.__name__)
47
49
  log(INFO, "Backend config: %s", backend_config)
48
50
 
51
+ if not pathlib.Path(work_dir).exists():
52
+ raise ValueError(f"Specified work_dir {work_dir} does not exist.")
53
+
49
54
  # Init ray and append working dir if needed
50
55
  runtime_env = (
51
56
  self._configure_runtime_env(work_dir=work_dir) if work_dir else None
@@ -138,22 +143,34 @@ class RayBackend(Backend):
138
143
  """
139
144
  node_id = message.metadata.dst_node_id
140
145
 
141
- # Submite a task to the pool
142
- future = await self.pool.submit(
143
- lambda a, a_fn, mssg, cid, state: a.run.remote(a_fn, mssg, cid, state),
144
- (app, message, str(node_id), context),
145
- )
146
+ try:
147
+ # Submite a task to the pool
148
+ future = await self.pool.submit(
149
+ lambda a, a_fn, mssg, cid, state: a.run.remote(a_fn, mssg, cid, state),
150
+ (app, message, str(node_id), context),
151
+ )
146
152
 
147
- await future
153
+ await future
148
154
 
149
- # Fetch result
150
- (
151
- out_mssg,
152
- updated_context,
153
- ) = await self.pool.fetch_result_and_return_actor_to_pool(future)
155
+ # Fetch result
156
+ (
157
+ out_mssg,
158
+ updated_context,
159
+ ) = await self.pool.fetch_result_and_return_actor_to_pool(future)
154
160
 
155
- return out_mssg, updated_context
161
+ return out_mssg, updated_context
162
+
163
+ except LoadClientAppError as load_ex:
164
+ log(
165
+ ERROR,
166
+ "An exception was raised when processing a message. Terminating %s",
167
+ self.__class__.__name__,
168
+ )
169
+ await self.terminate()
170
+ raise load_ex
156
171
 
157
172
  async def terminate(self) -> None:
158
173
  """Terminate all actors in actor pool."""
159
174
  await self.pool.terminate_all_actors()
175
+ ray.shutdown()
176
+ log(INFO, "Terminated %s", self.__class__.__name__)
@@ -19,7 +19,7 @@ import json
19
19
  from logging import ERROR, INFO
20
20
  from typing import Dict, Optional
21
21
 
22
- from flwr.client.clientapp import ClientApp, load_client_app
22
+ from flwr.client.client_app import ClientApp, load_client_app
23
23
  from flwr.client.node_state import NodeState
24
24
  from flwr.common.logger import log
25
25
  from flwr.server.superlink.state import StateFactory
@@ -25,7 +25,7 @@ import ray
25
25
  from ray import ObjectRef
26
26
  from ray.util.actor_pool import ActorPool
27
27
 
28
- from flwr.client.clientapp import ClientApp
28
+ from flwr.client.client_app import ClientApp, LoadClientAppError
29
29
  from flwr.common import Context, Message
30
30
  from flwr.common.logger import log
31
31
 
@@ -67,6 +67,9 @@ class VirtualClientEngineActor(ABC):
67
67
  # Handle task message
68
68
  out_message = app(message=message, context=context)
69
69
 
70
+ except LoadClientAppError as load_ex:
71
+ raise load_ex
72
+
70
73
  except Exception as ex:
71
74
  client_trace = traceback.format_exc()
72
75
  mssg = (
@@ -21,7 +21,7 @@ from typing import Optional
21
21
 
22
22
  from flwr import common
23
23
  from flwr.client import ClientFn
24
- from flwr.client.clientapp import ClientApp
24
+ from flwr.client.client_app import ClientApp
25
25
  from flwr.client.node_state import NodeState
26
26
  from flwr.common import Message, Metadata, RecordSet
27
27
  from flwr.common.constant import (