fedora-fl 2.1.0b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fedora/__init__.py +535 -0
- fedora/__version__.py +3 -0
- fedora/_circuits_cuda.py +92 -0
- fedora/_circuits_native.py +51 -0
- fedora/_robust_cuda.py +46 -0
- fedora/adapters/attestation_mock.py +15 -0
- fedora/adapters/capabilities.py +228 -0
- fedora/adapters/diagnostics.py +221 -0
- fedora/adapters/mpc_maskedsum.py +60 -0
- fedora/adapters/mpc_mock.py +29 -0
- fedora/adapters/mpc_paillier.py +109 -0
- fedora/adapters/ufcg_to_flare.py +520 -0
- fedora/adapters/ufcg_to_flower.py +32 -0
- fedora/adapters/ufcg_to_grpc.py +132 -0
- fedora/adapters/zk_mock.py +28 -0
- fedora/agents/__init__.py +57 -0
- fedora/agents/policy.py +222 -0
- fedora/agents/tasks.py +175 -0
- fedora/aggregation/__init__.py +148 -0
- fedora/aggregation/adaptive.py +770 -0
- fedora/aggregation/async_agg.py +275 -0
- fedora/aggregation/averaging.py +525 -0
- fedora/aggregation/base.py +216 -0
- fedora/aggregation/dp.py +1338 -0
- fedora/aggregation/lora.py +166 -0
- fedora/aggregation/mixed_precision.py +122 -0
- fedora/aggregation/robust.py +823 -0
- fedora/aggregation/secure.py +790 -0
- fedora/analytics.py +28 -0
- fedora/artifacts.py +207 -0
- fedora/assurance/ledger.py +47 -0
- fedora/attacks.py +16 -0
- fedora/backends/adaptive_compression.py +146 -0
- fedora/backends/aggregators.py +646 -0
- fedora/backends/api.py +55 -0
- fedora/backends/checkpoint.py +214 -0
- fedora/backends/compression.py +176 -0
- fedora/backends/flower_backend.py +45 -0
- fedora/backends/gpu.py +257 -0
- fedora/backends/grpc_backend.py +2110 -0
- fedora/backends/grpc_validation.py +151 -0
- fedora/backends/local_mp.py +733 -0
- fedora/backends/observability.py +158 -0
- fedora/backends/privacy.py +63 -0
- fedora/backends/protos/fedora_backend.proto +102 -0
- fedora/backends/ray_backend.py +630 -0
- fedora/circuits.py +108 -0
- fedora/cli.py +205 -0
- fedora/clients/__init__.py +81 -0
- fedora/clients/fastai_wrapper.py +234 -0
- fedora/clients/framework_utils.py +360 -0
- fedora/clients/huggingface_wrapper.py +287 -0
- fedora/clients/jax_wrapper.py +263 -0
- fedora/clients/keras_wrapper.py +299 -0
- fedora/clients/partial_training.py +272 -0
- fedora/clients/scaffold.py +70 -0
- fedora/clients/sdk.py +189 -0
- fedora/clients/sklearn_wrapper.py +251 -0
- fedora/clients/torch_wrapper.py +420 -0
- fedora/clients/xgboost_wrapper.py +250 -0
- fedora/compat/__init__.py +61 -0
- fedora/compat/flower.py +505 -0
- fedora/compat/migration.py +658 -0
- fedora/compliance.py +32 -0
- fedora/config.py +16 -0
- fedora/contracts.py +90 -0
- fedora/core/__init__.py +56 -0
- fedora/core/attacks.py +190 -0
- fedora/core/config.py +120 -0
- fedora/core/plugins.py +62 -0
- fedora/core/strategies.py +199 -0
- fedora/datasets/partitioners.py +81 -0
- fedora/engine/__init__.py +165 -0
- fedora/engine/client.py +409 -0
- fedora/engine/convergence.py +687 -0
- fedora/engine/diagnostics.py +313 -0
- fedora/engine/history.py +520 -0
- fedora/engine/round.py +409 -0
- fedora/engine/scheduler.py +656 -0
- fedora/engine/server.py +586 -0
- fedora/engine/state.py +266 -0
- fedora/engine/types.py +361 -0
- fedora/engine/validation.py +360 -0
- fedora/enterprise/__init__.py +316 -0
- fedora/enterprise/advanced_analytics.py +548 -0
- fedora/enterprise/analytics.py +263 -0
- fedora/enterprise/automated_compliance.py +291 -0
- fedora/enterprise/bench.py +115 -0
- fedora/enterprise/cli/__init__.py +34 -0
- fedora/enterprise/cli/__main__.py +8 -0
- fedora/enterprise/cli/_helpers.py +76 -0
- fedora/enterprise/cli/bench_cmds.py +101 -0
- fedora/enterprise/cli/compliance_cmds.py +805 -0
- fedora/enterprise/cli/config_cmds.py +584 -0
- fedora/enterprise/cli/deploy_cmds.py +229 -0
- fedora/enterprise/cli/monitor_cmds.py +92 -0
- fedora/enterprise/cli/run_cmds.py +342 -0
- fedora/enterprise/cli/security_cmds.py +453 -0
- fedora/enterprise/cli/ufcg_cmds.py +467 -0
- fedora/enterprise/cli_utils.py +273 -0
- fedora/enterprise/compliance.py +623 -0
- fedora/enterprise/config_validation.py +364 -0
- fedora/enterprise/deployment.py +1034 -0
- fedora/enterprise/flower_bridge.py +560 -0
- fedora/enterprise/incidents.py +420 -0
- fedora/enterprise/integrations.py +54 -0
- fedora/enterprise/mlops.py +370 -0
- fedora/enterprise/monitoring.py +472 -0
- fedora/enterprise/mpc.py +400 -0
- fedora/enterprise/observability.py +128 -0
- fedora/enterprise/pipelines.py +121 -0
- fedora/enterprise/policies.py +300 -0
- fedora/enterprise/policy_engines.py +89 -0
- fedora/enterprise/privacy.py +38 -0
- fedora/enterprise/release.py +71 -0
- fedora/enterprise/scalability.py +538 -0
- fedora/enterprise/security.py +774 -0
- fedora/enterprise/smart_config.py +420 -0
- fedora/enterprise/templates.py +385 -0
- fedora/enterprise/threat_intelligence.py +312 -0
- fedora/enterprise/trust.py +28 -0
- fedora/evidence.py +651 -0
- fedora/exceptions.py +64 -0
- fedora/integrations.py +32 -0
- fedora/knowledge/__init__.py +390 -0
- fedora/knowledge/adapter.py +638 -0
- fedora/knowledge/adoption.py +647 -0
- fedora/knowledge/agent.py +299 -0
- fedora/knowledge/agentsim.py +432 -0
- fedora/knowledge/base.py +365 -0
- fedora/knowledge/channel.py +114 -0
- fedora/knowledge/eval_result.py +495 -0
- fedora/knowledge/example.py +214 -0
- fedora/knowledge/extractors.py +65 -0
- fedora/knowledge/fact_bundle.py +231 -0
- fedora/knowledge/federate.py +391 -0
- fedora/knowledge/logits.py +355 -0
- fedora/knowledge/memory.py +743 -0
- fedora/knowledge/pipeline.py +565 -0
- fedora/knowledge/policy.py +283 -0
- fedora/knowledge/privacy/__init__.py +9 -0
- fedora/knowledge/privacy/canary.py +200 -0
- fedora/knowledge/prototype.py +323 -0
- fedora/knowledge/serialization.py +321 -0
- fedora/knowledge/skill.py +682 -0
- fedora/knowledge/state.py +444 -0
- fedora/knowledge/tensor.py +470 -0
- fedora/knowledge/threats.py +255 -0
- fedora/knowledge/tool_trace.py +344 -0
- fedora/knowledge/transport.py +210 -0
- fedora/knowledge/types.py +403 -0
- fedora/knowledge/validation.py +678 -0
- fedora/mpc.py +32 -0
- fedora/observability.py +32 -0
- fedora/pipelines.py +32 -0
- fedora/planning.py +465 -0
- fedora/plugins.py +16 -0
- fedora/policies.py +32 -0
- fedora/policy_engines.py +32 -0
- fedora/privacy.py +32 -0
- fedora/py.typed +0 -0
- fedora/reference_apps/__init__.py +1 -0
- fedora/reference_apps/fixtures/support_agents.json +151 -0
- fedora/reference_apps/support_agents.py +713 -0
- fedora/release.py +32 -0
- fedora/schema_validation.py +156 -0
- fedora/schemas/adapter_diagnostic.schema.json +40 -0
- fedora/schemas/evidence_manifest.schema.json +297 -0
- fedora/schemas/grpc_deployment_validation.schema.json +42 -0
- fedora/schemas/proof_summary.schema.json +114 -0
- fedora/schemas/receipt.schema.json +70 -0
- fedora/security/__init__.py +62 -0
- fedora/security/attacks.py +427 -0
- fedora/security/audit.py +586 -0
- fedora/security/benchmarks.py +389 -0
- fedora/security/defenses.py +442 -0
- fedora/security/demo.py +211 -0
- fedora/security/secret_sharing.py +271 -0
- fedora/security/threat_model.py +502 -0
- fedora/security/trust.py +512 -0
- fedora/security.py +32 -0
- fedora/simulation/__init__.py +54 -0
- fedora/simulation/data.py +348 -0
- fedora/simulation/device_simulator.py +445 -0
- fedora/simulation/examples.py +395 -0
- fedora/simulation/history.py +359 -0
- fedora/simulation/runner.py +945 -0
- fedora/simulation/virtual_client.py +573 -0
- fedora/starter_pack/plugins/sample_anomaly.py +26 -0
- fedora/strategies.py +16 -0
- fedora/transport/__init__.py +85 -0
- fedora/transport/base.py +292 -0
- fedora/transport/grpc_transport.py +1256 -0
- fedora/transport/local.py +470 -0
- fedora/transport/serialization.py +343 -0
- fedora/transport/test_local_transport.py +239 -0
- fedora/transport/tls_config.py +261 -0
- fedora/transport/websocket_transport.py +1037 -0
- fedora/trust.py +32 -0
- fedora/ufcg/__init__.py +25 -0
- fedora/ufcg/cost.py +61 -0
- fedora/ufcg/ir.py +178 -0
- fedora/ufcg/planner.py +168 -0
- fedora_fl-2.1.0b2.dist-info/METADATA +758 -0
- fedora_fl-2.1.0b2.dist-info/RECORD +209 -0
- fedora_fl-2.1.0b2.dist-info/WHEEL +5 -0
- fedora_fl-2.1.0b2.dist-info/entry_points.txt +2 -0
- fedora_fl-2.1.0b2.dist-info/licenses/LICENSE +172 -0
- fedora_fl-2.1.0b2.dist-info/top_level.txt +1 -0
fedora/__init__.py
ADDED
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
"""Fedora: federated knowledge learning for agents and FL systems.
|
|
2
|
+
|
|
3
|
+
Fedora helps distributed agents and organizations share useful learned knowledge
|
|
4
|
+
without sharing raw private data, full local memory, or unrestricted internal
|
|
5
|
+
state. Classic federated learning remains the ``parameters`` artifact type; the
|
|
6
|
+
same planning surface can also represent adapters, memories, skills, traces,
|
|
7
|
+
evaluation results, facts, policies, and distilled examples.
|
|
8
|
+
|
|
9
|
+
It provides:
|
|
10
|
+
|
|
11
|
+
- **Clean API**: Decorator and class-based client abstractions
|
|
12
|
+
- **Simulation**: Run FL experiments locally without distributed infrastructure
|
|
13
|
+
- **Knowledge Artifacts**: Typed exchange units for federated knowledge workflows
|
|
14
|
+
- **Privacy and Trust Controls**: Threat models, robust aggregation, differential privacy
|
|
15
|
+
- **Async Capable**: FedBuff-style buffered aggregation, deadline-based execution
|
|
16
|
+
- **Transport Agnostic**: Local, gRPC, and WebSocket communication
|
|
17
|
+
- **Aggregator Registry**: FedAvg, Krum, MultiKrum, Bulyan, FedAdam, and more
|
|
18
|
+
- **Plan-First API**: Compile UFCG programs into inspectable plans with plan IDs
|
|
19
|
+
|
|
20
|
+
Quick Start:
|
|
21
|
+
|
|
22
|
+
import fedora
|
|
23
|
+
import numpy as np
|
|
24
|
+
|
|
25
|
+
@fedora.client
|
|
26
|
+
def train(parameters, config):
|
|
27
|
+
updated = [p + np.random.randn(*p.shape) * 0.01 for p in parameters]
|
|
28
|
+
return updated, 100, {"loss": 0.5}
|
|
29
|
+
|
|
30
|
+
history = fedora.simulate(
|
|
31
|
+
client_fn=lambda cid: train,
|
|
32
|
+
num_clients=10,
|
|
33
|
+
num_rounds=5,
|
|
34
|
+
)
|
|
35
|
+
print(history.summary())
|
|
36
|
+
|
|
37
|
+
Documentation: https://github.com/uib-slate/fedora
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from __future__ import annotations
|
|
41
|
+
|
|
42
|
+
__version__ = "2.1.0b2"
|
|
43
|
+
|
|
44
|
+
# Core engine abstractions
|
|
45
|
+
# Aggregation strategies
|
|
46
|
+
from .adapters.capabilities import (
|
|
47
|
+
BACKEND_CAPABILITY_MATRIX,
|
|
48
|
+
get_backend_capabilities,
|
|
49
|
+
validate_adapter_diagnostics,
|
|
50
|
+
)
|
|
51
|
+
from .aggregation import (
|
|
52
|
+
SCAFFOLD,
|
|
53
|
+
Aggregator,
|
|
54
|
+
Bulyan,
|
|
55
|
+
ClipNorm,
|
|
56
|
+
CoordinateMedian,
|
|
57
|
+
DPAggregator,
|
|
58
|
+
DPConfig,
|
|
59
|
+
FedAdagrad,
|
|
60
|
+
FedAdam,
|
|
61
|
+
FedAvg,
|
|
62
|
+
FedNova,
|
|
63
|
+
FedProx,
|
|
64
|
+
FedYogi,
|
|
65
|
+
FoolsGold,
|
|
66
|
+
GaussianMechanism,
|
|
67
|
+
Krum,
|
|
68
|
+
LoRAAggregator,
|
|
69
|
+
LoRAFFA,
|
|
70
|
+
LoRAFlexLoRA,
|
|
71
|
+
LoRAMergedDelta,
|
|
72
|
+
MixedPrecisionAggregator,
|
|
73
|
+
MultiKrum,
|
|
74
|
+
PrivacyAccountant,
|
|
75
|
+
RDPAccountant,
|
|
76
|
+
SecAgg,
|
|
77
|
+
SecAggPlus,
|
|
78
|
+
SecureAggregator,
|
|
79
|
+
SimpleAccountant,
|
|
80
|
+
TrimmedMean,
|
|
81
|
+
ZCDPAccountant,
|
|
82
|
+
get_aggregator,
|
|
83
|
+
list_aggregators,
|
|
84
|
+
register_aggregator,
|
|
85
|
+
)
|
|
86
|
+
from .artifacts import (
|
|
87
|
+
ARTIFACT_PROFILES,
|
|
88
|
+
ARTIFACT_THREAT_NOTES,
|
|
89
|
+
ARTIFACT_TYPES,
|
|
90
|
+
DEFAULT_ARTIFACT_TYPE,
|
|
91
|
+
ArtifactProfile,
|
|
92
|
+
ArtifactSpec,
|
|
93
|
+
describe_artifact,
|
|
94
|
+
get_artifact_profile,
|
|
95
|
+
validate_artifact_type,
|
|
96
|
+
)
|
|
97
|
+
from .backends.grpc_validation import (
|
|
98
|
+
raise_for_invalid_grpc_deployment,
|
|
99
|
+
validate_grpc_deployment_config,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Framework client wrappers (optional dependencies)
|
|
103
|
+
from .clients import (
|
|
104
|
+
FastaiClient,
|
|
105
|
+
HuggingFaceClient,
|
|
106
|
+
JaxClient,
|
|
107
|
+
LayerSelector,
|
|
108
|
+
PartialTrainingClient,
|
|
109
|
+
PyTorchClient,
|
|
110
|
+
SklearnClient,
|
|
111
|
+
TensorFlowClient,
|
|
112
|
+
XGBoostClient,
|
|
113
|
+
detect_framework,
|
|
114
|
+
get_framework_params,
|
|
115
|
+
set_framework_params,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
# Compatibility layer (optional, for Flower migration)
|
|
119
|
+
from .compat import (
|
|
120
|
+
FedoraFlowerAdapter,
|
|
121
|
+
FlowerClientAdapter,
|
|
122
|
+
FlowerStrategyAdapter,
|
|
123
|
+
MigrationHelper,
|
|
124
|
+
MigrationReport,
|
|
125
|
+
)
|
|
126
|
+
from .engine import (
|
|
127
|
+
Client,
|
|
128
|
+
ClientConfig,
|
|
129
|
+
ClientProxy,
|
|
130
|
+
ClientStatus,
|
|
131
|
+
Config,
|
|
132
|
+
EvalResult,
|
|
133
|
+
FederationServer,
|
|
134
|
+
FitResult,
|
|
135
|
+
Metrics,
|
|
136
|
+
NDArrays,
|
|
137
|
+
NumPyClient,
|
|
138
|
+
Parameters,
|
|
139
|
+
RoundConfig,
|
|
140
|
+
RoundManager,
|
|
141
|
+
RoundMode,
|
|
142
|
+
RoundResult,
|
|
143
|
+
Scalar,
|
|
144
|
+
ServerConfig,
|
|
145
|
+
ServerState,
|
|
146
|
+
client,
|
|
147
|
+
)
|
|
148
|
+
from .evidence import (
|
|
149
|
+
build_evidence_bundle,
|
|
150
|
+
run_proof_workflow,
|
|
151
|
+
verify_evidence_bundle,
|
|
152
|
+
verify_receipt_chain,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Exception hierarchy
|
|
156
|
+
from .exceptions import (
|
|
157
|
+
AggregationError,
|
|
158
|
+
ClientError,
|
|
159
|
+
ConfigurationError,
|
|
160
|
+
FedoraError,
|
|
161
|
+
InsecureTransportWarning,
|
|
162
|
+
PrivacyBudgetExhausted,
|
|
163
|
+
RoundError,
|
|
164
|
+
SecurityError,
|
|
165
|
+
SerializationError,
|
|
166
|
+
TransportError,
|
|
167
|
+
)
|
|
168
|
+
from .knowledge import (
|
|
169
|
+
AdoptionGate,
|
|
170
|
+
ArtifactValidationIssue,
|
|
171
|
+
ArtifactValidationResult,
|
|
172
|
+
CanaryAudit,
|
|
173
|
+
CanaryFinding,
|
|
174
|
+
CanaryReport,
|
|
175
|
+
FederationResult,
|
|
176
|
+
KnowledgeArtifact,
|
|
177
|
+
KnowledgeThreatControls,
|
|
178
|
+
KnowledgeThreatModel,
|
|
179
|
+
MergeReport,
|
|
180
|
+
RejectedArtifact,
|
|
181
|
+
federate,
|
|
182
|
+
filter_valid_artifacts,
|
|
183
|
+
merge_knowledge_artifacts,
|
|
184
|
+
validate_knowledge_artifact,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Plan-first API
|
|
188
|
+
from .planning import KnowledgeObjective, Plan, ThreatScenario, list_scenarios, plan, scenario
|
|
189
|
+
from .schema_validation import SCHEMA_NAMES, load_schema, validate_json_schema
|
|
190
|
+
|
|
191
|
+
# Security module
|
|
192
|
+
from .security import (
|
|
193
|
+
Attack,
|
|
194
|
+
AuditEvent,
|
|
195
|
+
AuditTrail,
|
|
196
|
+
BackdoorAttack,
|
|
197
|
+
ContributionScoring,
|
|
198
|
+
Defense,
|
|
199
|
+
DefenseRecommendation,
|
|
200
|
+
FreeRider,
|
|
201
|
+
GradientInversion,
|
|
202
|
+
LabelFlip,
|
|
203
|
+
ModelReplace,
|
|
204
|
+
NormClipping,
|
|
205
|
+
ScalingAttack,
|
|
206
|
+
ShamirSecretSharing,
|
|
207
|
+
SignFlip,
|
|
208
|
+
SimilarityFilter,
|
|
209
|
+
SpectralDetector,
|
|
210
|
+
ThreatModel,
|
|
211
|
+
TrustManager,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
# Simulation engine
|
|
215
|
+
from .simulation import (
|
|
216
|
+
DataDistributor,
|
|
217
|
+
DeviceProfile,
|
|
218
|
+
DeviceSimulator,
|
|
219
|
+
DeviceType,
|
|
220
|
+
RoundHistory,
|
|
221
|
+
SimulationHistory,
|
|
222
|
+
SimulationRunner,
|
|
223
|
+
Subset,
|
|
224
|
+
VirtualClient,
|
|
225
|
+
VirtualClientManager,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
# Transport layer
|
|
229
|
+
from .transport import (
|
|
230
|
+
ClientTransport,
|
|
231
|
+
GrpcClientTransport,
|
|
232
|
+
GrpcServerTransport,
|
|
233
|
+
LocalClientTransport,
|
|
234
|
+
LocalServerTransport,
|
|
235
|
+
ServerTransport,
|
|
236
|
+
TLSConfig,
|
|
237
|
+
WebSocketClientTransport,
|
|
238
|
+
WebSocketServerTransport,
|
|
239
|
+
deserialize_client_config,
|
|
240
|
+
deserialize_eval_result,
|
|
241
|
+
deserialize_fit_result,
|
|
242
|
+
deserialize_parameters,
|
|
243
|
+
get_transport,
|
|
244
|
+
list_transports,
|
|
245
|
+
parse_transport_url,
|
|
246
|
+
register_transport,
|
|
247
|
+
serialize_client_config,
|
|
248
|
+
serialize_eval_result,
|
|
249
|
+
serialize_fit_result,
|
|
250
|
+
serialize_parameters,
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
# Convenience function: simulate is the main entry point for FL experiments
|
|
255
|
+
def simulate(
|
|
256
|
+
client_fn,
|
|
257
|
+
num_clients: int,
|
|
258
|
+
num_rounds: int,
|
|
259
|
+
aggregator: str | Aggregator | None = None,
|
|
260
|
+
artifact: str = DEFAULT_ARTIFACT_TYPE,
|
|
261
|
+
threat_model: ThreatModel | None = None,
|
|
262
|
+
attack_fn=None,
|
|
263
|
+
defenses: list | None = None,
|
|
264
|
+
**kwargs,
|
|
265
|
+
) -> SimulationHistory:
|
|
266
|
+
"""Run a federated learning simulation.
|
|
267
|
+
|
|
268
|
+
This is the main entry point for running FL experiments locally. It handles
|
|
269
|
+
creating virtual clients, managing communication, and aggregating updates.
|
|
270
|
+
|
|
271
|
+
All security features compose automatically:
|
|
272
|
+
- Pass a ThreatModel to auto-select aggregator, DP, and defenses
|
|
273
|
+
- Pass an explicit aggregator to override the auto-selection
|
|
274
|
+
- Pass defenses to filter malicious updates before aggregation
|
|
275
|
+
- Pass attack_fn to simulate Byzantine clients
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
client_fn: Callable that takes client_id and returns a Client instance.
|
|
279
|
+
num_clients: Total number of virtual clients.
|
|
280
|
+
num_rounds: Number of training rounds.
|
|
281
|
+
aggregator: Aggregator instance or name string (e.g., "krum", "fedavg").
|
|
282
|
+
If None and threat_model is set, auto-selected from threat model.
|
|
283
|
+
artifact: Knowledge artifact type exchanged by this run
|
|
284
|
+
(e.g., "parameters", "adapter", "tool_trace").
|
|
285
|
+
threat_model: ThreatModel for automatic defense configuration.
|
|
286
|
+
attack_fn: Function(client_id) -> Attack or None for simulation.
|
|
287
|
+
defenses: List of Defense instances to filter results before aggregation.
|
|
288
|
+
**kwargs: Additional arguments passed to SimulationRunner
|
|
289
|
+
(data, data_distribution, seed, dropout_rate, etc.)
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
SimulationHistory with results, metrics, and analytics.
|
|
293
|
+
|
|
294
|
+
Examples:
|
|
295
|
+
Basic simulation::
|
|
296
|
+
|
|
297
|
+
history = fedora.simulate(
|
|
298
|
+
client_fn=lambda cid: MyClient(),
|
|
299
|
+
num_clients=10,
|
|
300
|
+
num_rounds=5,
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
With threat model (auto-configures everything)::
|
|
304
|
+
|
|
305
|
+
history = fedora.simulate(
|
|
306
|
+
client_fn=lambda cid: MyClient(),
|
|
307
|
+
num_clients=50,
|
|
308
|
+
num_rounds=10,
|
|
309
|
+
threat_model=fedora.ThreatModel(
|
|
310
|
+
byzantine_fraction=0.2,
|
|
311
|
+
privacy_level="strong",
|
|
312
|
+
),
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
With explicit aggregator + attacks::
|
|
316
|
+
|
|
317
|
+
history = fedora.simulate(
|
|
318
|
+
client_fn=lambda cid: MyClient(),
|
|
319
|
+
num_clients=50,
|
|
320
|
+
num_rounds=10,
|
|
321
|
+
aggregator=fedora.Krum(num_byzantine=5),
|
|
322
|
+
attack_fn=lambda cid: fedora.ScalingAttack(10) if int(cid) < 10 else None,
|
|
323
|
+
defenses=[fedora.NormClipping(1.0)],
|
|
324
|
+
)
|
|
325
|
+
"""
|
|
326
|
+
# Resolve aggregator: instance or string name
|
|
327
|
+
agg_instance = None
|
|
328
|
+
agg_name = None
|
|
329
|
+
if isinstance(aggregator, str):
|
|
330
|
+
agg_name = aggregator
|
|
331
|
+
elif aggregator is not None:
|
|
332
|
+
agg_instance = aggregator
|
|
333
|
+
|
|
334
|
+
runner = SimulationRunner(
|
|
335
|
+
client_fn=client_fn,
|
|
336
|
+
num_clients=num_clients,
|
|
337
|
+
num_rounds=num_rounds,
|
|
338
|
+
aggregator=agg_instance,
|
|
339
|
+
aggregator_name=agg_name,
|
|
340
|
+
artifact=artifact,
|
|
341
|
+
threat_model=threat_model,
|
|
342
|
+
attack_fn=attack_fn,
|
|
343
|
+
defenses=defenses,
|
|
344
|
+
**kwargs,
|
|
345
|
+
)
|
|
346
|
+
return runner.run()
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
__all__ = [
|
|
350
|
+
"__version__",
|
|
351
|
+
# Knowledge artifacts
|
|
352
|
+
"ARTIFACT_PROFILES",
|
|
353
|
+
"ARTIFACT_TYPES",
|
|
354
|
+
"ARTIFACT_THREAT_NOTES",
|
|
355
|
+
"ArtifactProfile",
|
|
356
|
+
"ArtifactSpec",
|
|
357
|
+
"DEFAULT_ARTIFACT_TYPE",
|
|
358
|
+
"KnowledgeArtifact",
|
|
359
|
+
"KnowledgeObjective",
|
|
360
|
+
"KnowledgeThreatControls",
|
|
361
|
+
"KnowledgeThreatModel",
|
|
362
|
+
"FederationResult",
|
|
363
|
+
"AdoptionGate",
|
|
364
|
+
"CanaryAudit",
|
|
365
|
+
"CanaryFinding",
|
|
366
|
+
"CanaryReport",
|
|
367
|
+
"ArtifactValidationIssue",
|
|
368
|
+
"ArtifactValidationResult",
|
|
369
|
+
"MergeReport",
|
|
370
|
+
"RejectedArtifact",
|
|
371
|
+
"describe_artifact",
|
|
372
|
+
"filter_valid_artifacts",
|
|
373
|
+
"federate",
|
|
374
|
+
"get_artifact_profile",
|
|
375
|
+
"merge_knowledge_artifacts",
|
|
376
|
+
"validate_knowledge_artifact",
|
|
377
|
+
"validate_artifact_type",
|
|
378
|
+
# Core engine
|
|
379
|
+
"Client",
|
|
380
|
+
"NumPyClient",
|
|
381
|
+
"client",
|
|
382
|
+
"ClientConfig",
|
|
383
|
+
"ClientProxy",
|
|
384
|
+
"ClientStatus",
|
|
385
|
+
"Config",
|
|
386
|
+
"EvalResult",
|
|
387
|
+
"FitResult",
|
|
388
|
+
"Metrics",
|
|
389
|
+
"NDArrays",
|
|
390
|
+
"Parameters",
|
|
391
|
+
"Scalar",
|
|
392
|
+
"ServerState",
|
|
393
|
+
"RoundConfig",
|
|
394
|
+
"RoundMode",
|
|
395
|
+
"RoundManager",
|
|
396
|
+
"RoundResult",
|
|
397
|
+
"FederationServer",
|
|
398
|
+
"ServerConfig",
|
|
399
|
+
# Aggregation
|
|
400
|
+
"Aggregator",
|
|
401
|
+
"FedAvg",
|
|
402
|
+
"FedProx",
|
|
403
|
+
"FedNova",
|
|
404
|
+
"SCAFFOLD",
|
|
405
|
+
"TrimmedMean",
|
|
406
|
+
"CoordinateMedian",
|
|
407
|
+
"Krum",
|
|
408
|
+
"MultiKrum",
|
|
409
|
+
"Bulyan",
|
|
410
|
+
"FoolsGold",
|
|
411
|
+
"LoRAAggregator",
|
|
412
|
+
"LoRAFFA",
|
|
413
|
+
"LoRAFlexLoRA",
|
|
414
|
+
"LoRAMergedDelta",
|
|
415
|
+
"FedAdam",
|
|
416
|
+
"FedAdagrad",
|
|
417
|
+
"FedYogi",
|
|
418
|
+
"DPConfig",
|
|
419
|
+
"GaussianMechanism",
|
|
420
|
+
"ClipNorm",
|
|
421
|
+
"DPAggregator",
|
|
422
|
+
"PrivacyAccountant",
|
|
423
|
+
"SimpleAccountant",
|
|
424
|
+
"RDPAccountant",
|
|
425
|
+
"ZCDPAccountant",
|
|
426
|
+
"SecureAggregator",
|
|
427
|
+
"SecAgg",
|
|
428
|
+
"SecAggPlus",
|
|
429
|
+
"MixedPrecisionAggregator",
|
|
430
|
+
"get_aggregator",
|
|
431
|
+
"list_aggregators",
|
|
432
|
+
"register_aggregator",
|
|
433
|
+
# Security
|
|
434
|
+
"ThreatModel",
|
|
435
|
+
"DefenseRecommendation",
|
|
436
|
+
"Attack",
|
|
437
|
+
"LabelFlip",
|
|
438
|
+
"BackdoorAttack",
|
|
439
|
+
"SignFlip",
|
|
440
|
+
"ScalingAttack",
|
|
441
|
+
"ModelReplace",
|
|
442
|
+
"FreeRider",
|
|
443
|
+
"GradientInversion",
|
|
444
|
+
"Defense",
|
|
445
|
+
"NormClipping",
|
|
446
|
+
"ContributionScoring",
|
|
447
|
+
"SimilarityFilter",
|
|
448
|
+
"SpectralDetector",
|
|
449
|
+
"TrustManager",
|
|
450
|
+
"AuditEvent",
|
|
451
|
+
"AuditTrail",
|
|
452
|
+
"ShamirSecretSharing",
|
|
453
|
+
# Simulation
|
|
454
|
+
"SimulationRunner",
|
|
455
|
+
"VirtualClientManager",
|
|
456
|
+
"VirtualClient",
|
|
457
|
+
"DataDistributor",
|
|
458
|
+
"Subset",
|
|
459
|
+
"SimulationHistory",
|
|
460
|
+
"RoundHistory",
|
|
461
|
+
"DeviceSimulator",
|
|
462
|
+
"DeviceProfile",
|
|
463
|
+
"DeviceType",
|
|
464
|
+
"simulate",
|
|
465
|
+
# Transport
|
|
466
|
+
"ServerTransport",
|
|
467
|
+
"ClientTransport",
|
|
468
|
+
"LocalServerTransport",
|
|
469
|
+
"LocalClientTransport",
|
|
470
|
+
"GrpcServerTransport",
|
|
471
|
+
"GrpcClientTransport",
|
|
472
|
+
"WebSocketServerTransport",
|
|
473
|
+
"WebSocketClientTransport",
|
|
474
|
+
"register_transport",
|
|
475
|
+
"get_transport",
|
|
476
|
+
"list_transports",
|
|
477
|
+
"parse_transport_url",
|
|
478
|
+
"serialize_parameters",
|
|
479
|
+
"deserialize_parameters",
|
|
480
|
+
"serialize_fit_result",
|
|
481
|
+
"deserialize_fit_result",
|
|
482
|
+
"serialize_eval_result",
|
|
483
|
+
"deserialize_eval_result",
|
|
484
|
+
"serialize_client_config",
|
|
485
|
+
"deserialize_client_config",
|
|
486
|
+
"TLSConfig",
|
|
487
|
+
# Exceptions
|
|
488
|
+
"FedoraError",
|
|
489
|
+
"ConfigurationError",
|
|
490
|
+
"AggregationError",
|
|
491
|
+
"ClientError",
|
|
492
|
+
"RoundError",
|
|
493
|
+
"SecurityError",
|
|
494
|
+
"TransportError",
|
|
495
|
+
"SerializationError",
|
|
496
|
+
"PrivacyBudgetExhausted",
|
|
497
|
+
"InsecureTransportWarning",
|
|
498
|
+
# Framework clients
|
|
499
|
+
"PyTorchClient",
|
|
500
|
+
"TensorFlowClient",
|
|
501
|
+
"JaxClient",
|
|
502
|
+
"SklearnClient",
|
|
503
|
+
"HuggingFaceClient",
|
|
504
|
+
"XGBoostClient",
|
|
505
|
+
"FastaiClient",
|
|
506
|
+
"PartialTrainingClient",
|
|
507
|
+
"LayerSelector",
|
|
508
|
+
"detect_framework",
|
|
509
|
+
"get_framework_params",
|
|
510
|
+
"set_framework_params",
|
|
511
|
+
# Compatibility
|
|
512
|
+
"FlowerClientAdapter",
|
|
513
|
+
"FedoraFlowerAdapter",
|
|
514
|
+
"FlowerStrategyAdapter",
|
|
515
|
+
"MigrationHelper",
|
|
516
|
+
"MigrationReport",
|
|
517
|
+
# Plan-first API
|
|
518
|
+
"Plan",
|
|
519
|
+
"ThreatScenario",
|
|
520
|
+
"list_scenarios",
|
|
521
|
+
"plan",
|
|
522
|
+
"scenario",
|
|
523
|
+
"build_evidence_bundle",
|
|
524
|
+
"run_proof_workflow",
|
|
525
|
+
"verify_evidence_bundle",
|
|
526
|
+
"verify_receipt_chain",
|
|
527
|
+
"BACKEND_CAPABILITY_MATRIX",
|
|
528
|
+
"get_backend_capabilities",
|
|
529
|
+
"validate_adapter_diagnostics",
|
|
530
|
+
"raise_for_invalid_grpc_deployment",
|
|
531
|
+
"validate_grpc_deployment_config",
|
|
532
|
+
"SCHEMA_NAMES",
|
|
533
|
+
"load_schema",
|
|
534
|
+
"validate_json_schema",
|
|
535
|
+
]
|
fedora/__version__.py
ADDED
fedora/_circuits_cuda.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
CUDA-accelerated fused circuit (optional).
|
|
5
|
+
|
|
6
|
+
This module uses CuPy if available to implement a fused
|
|
7
|
+
clip+mean+momentum step on the GPU. It is enabled when the environment
|
|
8
|
+
variable FEDORA_USE_CUDA_CIRCUITS is set to 1/true and CuPy is
|
|
9
|
+
importable. Results are converted back to NumPy arrays.
|
|
10
|
+
|
|
11
|
+
This path is intended for large tensors where device transfer overhead
|
|
12
|
+
is amortised. For small models, the CPU (NumPy/native) path may be
|
|
13
|
+
faster.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from collections.abc import Iterable, Mapping
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
|
|
20
|
+
try: # pragma: no cover - optional dependency
|
|
21
|
+
import cupy as cp # type: ignore
|
|
22
|
+
__cuda_available__ = True
|
|
23
|
+
except Exception: # pragma: no cover - optional
|
|
24
|
+
__cuda_available__ = False
|
|
25
|
+
|
|
26
|
+
Params = dict[str, np.ndarray]
|
|
27
|
+
Update = tuple[Params, int]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def clip_mean_momentum(
|
|
31
|
+
updates: Iterable[Update],
|
|
32
|
+
*,
|
|
33
|
+
clip_norm: float,
|
|
34
|
+
lr: float,
|
|
35
|
+
momentum: float,
|
|
36
|
+
prev: Mapping[str, np.ndarray] | None = None,
|
|
37
|
+
): # -> Params
|
|
38
|
+
if not __cuda_available__:
|
|
39
|
+
raise RuntimeError("CuPy is not available; cannot use CUDA circuits")
|
|
40
|
+
|
|
41
|
+
ups = list(updates)
|
|
42
|
+
if not ups:
|
|
43
|
+
return {}
|
|
44
|
+
|
|
45
|
+
# Move to device and pre-clip
|
|
46
|
+
weights = cp.asarray([float(n) for (_p, n) in ups], dtype=cp.float32)
|
|
47
|
+
total = float(cp.sum(weights)) if float(cp.sum(weights)) > 0 else 1.0
|
|
48
|
+
keys = list(ups[0][0].keys())
|
|
49
|
+
clipped: list[dict[str, cp.ndarray]] = []
|
|
50
|
+
for p, _n in ups:
|
|
51
|
+
d: dict[str, cp.ndarray] = {}
|
|
52
|
+
if clip_norm and float(clip_norm) > 0.0:
|
|
53
|
+
sq = 0.0
|
|
54
|
+
for v in p.values():
|
|
55
|
+
a = cp.asarray(v, dtype=cp.float32)
|
|
56
|
+
sq += float(cp.sum(a * a))
|
|
57
|
+
norm = float(sq) ** 0.5 if sq > 1e-12 else 1e-6
|
|
58
|
+
factor = min(1.0, float(clip_norm) / norm)
|
|
59
|
+
else:
|
|
60
|
+
factor = 1.0
|
|
61
|
+
f = float(factor)
|
|
62
|
+
for k, v in p.items():
|
|
63
|
+
d[k] = cp.asarray(v, dtype=cp.float32) * f
|
|
64
|
+
clipped.append(d)
|
|
65
|
+
|
|
66
|
+
# Mean aggregate on device
|
|
67
|
+
mean_params: dict[str, cp.ndarray] = {}
|
|
68
|
+
wnorm = weights / float(total)
|
|
69
|
+
for k in keys:
|
|
70
|
+
acc = None
|
|
71
|
+
for i, d in enumerate(clipped):
|
|
72
|
+
contrib = d[k] * wnorm[i]
|
|
73
|
+
acc = contrib if acc is None else (acc + contrib)
|
|
74
|
+
mean_params[k] = acc if acc is not None else cp.zeros_like(clipped[0][k])
|
|
75
|
+
|
|
76
|
+
if prev is None:
|
|
77
|
+
return {k: cp.asnumpy(v) for k, v in mean_params.items()}
|
|
78
|
+
|
|
79
|
+
# Momentum step on device (stateless v for now)
|
|
80
|
+
mu = float(momentum)
|
|
81
|
+
lr_f = float(lr)
|
|
82
|
+
out: Params = {}
|
|
83
|
+
for k, a in mean_params.items():
|
|
84
|
+
w_prev = cp.asarray(prev.get(k, cp.asnumpy(a)), dtype=cp.float32)
|
|
85
|
+
g = a - w_prev
|
|
86
|
+
v = mu * g + g
|
|
87
|
+
out[k] = cp.asnumpy(w_prev + lr_f * v)
|
|
88
|
+
return out
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
__all__ = ["clip_mean_momentum", "__cuda_available__"]
|
|
92
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Native circuits shim.
|
|
2
|
+
|
|
3
|
+
This module attempts to import a compiled extension (e.g., built via pybind11)
|
|
4
|
+
exposing `clip_mean_momentum`. If not present, the symbol exists but raises at
|
|
5
|
+
call time unless you enable the NumPy fallback in fedora.circuits instead.
|
|
6
|
+
|
|
7
|
+
Build guidance:
|
|
8
|
+
- Provide a compiled module named `fedora._circuits_native_ext` exposing
|
|
9
|
+
`clip_mean_momentum(updates, *, clip_norm, lr, momentum, prev=None)`.
|
|
10
|
+
- Set `FEDORA_USE_NATIVE_CIRCUITS=1` to instruct fedora.circuits to prefer this
|
|
11
|
+
native path at runtime.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
try: # pragma: no cover - optional build
|
|
17
|
+
from fedora._circuits_native_ext import clip_mean_momentum as clip_mean_momentum # type: ignore
|
|
18
|
+
from fedora._circuits_native_ext import (
|
|
19
|
+
coord_median_matrix as coord_median_matrix, # type: ignore
|
|
20
|
+
)
|
|
21
|
+
from fedora._circuits_native_ext import (
|
|
22
|
+
krum_index as krum_index, # type: ignore
|
|
23
|
+
)
|
|
24
|
+
from fedora._circuits_native_ext import (
|
|
25
|
+
krum_matrix as krum_matrix, # type: ignore
|
|
26
|
+
)
|
|
27
|
+
from fedora._circuits_native_ext import (
|
|
28
|
+
multikrum_indices as multikrum_indices, # type: ignore
|
|
29
|
+
)
|
|
30
|
+
from fedora._circuits_native_ext import (
|
|
31
|
+
trimmed_mean_matrix as trimmed_mean_matrix, # type: ignore
|
|
32
|
+
)
|
|
33
|
+
__native__ = True
|
|
34
|
+
except Exception: # pragma: no cover - optional
|
|
35
|
+
__native__ = False
|
|
36
|
+
|
|
37
|
+
def clip_mean_momentum(*_args, **_kwargs): # type: ignore[no-redef]
|
|
38
|
+
raise RuntimeError(
|
|
39
|
+
"Native circuits extension not available. Install/build the pybind11 module "
|
|
40
|
+
"(fedora._circuits_native_ext) or use the NumPy fallback in fedora.circuits."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
__all__ = ["clip_mean_momentum", "__native__"]
|
|
44
|
+
if __native__:
|
|
45
|
+
__all__ += [
|
|
46
|
+
"trimmed_mean_matrix",
|
|
47
|
+
"coord_median_matrix",
|
|
48
|
+
"krum_matrix",
|
|
49
|
+
"krum_index",
|
|
50
|
+
"multikrum_indices",
|
|
51
|
+
]
|