API Reference¶
Aggregation¶
groupoid.aggregation.TransportGroupoidAggregator
dataclass
¶
Federated aggregator using groupoid transport and Riemannian geometry.
Given a network of clients with local model parameters on a Riemannian manifold, this aggregator: - Uses parallel transport (groupoid morphisms) to align parameters - Checks cohomological consistency before aggregation - Computes intrinsic Karcher mean on the parameter manifold - Distributes the result back via inverse transport
Parameters¶
manifold A geomstats manifold instance for the parameter space. graph Directed graph of the client network. base_node The node to which all parameters are transported for aggregation. consistency_threshold Maximum H^1 norm before raising a consistency warning.
Source code in groupoid/aggregation.py
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | |
aggregate(client_params, weights=None)
¶
Run one round of groupoid-aware federated aggregation.
Parameters¶
client_params Map from client node ID to local model parameters. weights Optional per-client weights for the Karcher mean.
Returns¶
FederatedRound The aggregation result including global params, consistency metrics, and per-client local updates.
Source code in groupoid/aggregation.py
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | |
check_consistency(client_params)
¶
Check cohomological consistency of current transport maps.
Returns the H^1 norm. A value near zero indicates that the local models can be consistently aggregated.
Source code in groupoid/aggregation.py
124 125 126 127 128 129 130 131 132 133 | |
register_transport(source, target, matrix)
¶
Register a transport map between two clients.
Source code in groupoid/aggregation.py
84 85 86 87 88 89 90 91 | |
groupoid.aggregation.FederatedRound
dataclass
¶
Result of a single federated aggregation round.
Source code in groupoid/aggregation.py
42 43 44 45 46 47 48 49 50 51 | |
Manifold Operations¶
groupoid.manifold.karcher_mean(manifold, points, weights=None, max_iter=100, tol=1e-06)
¶
Compute the Karcher (Frechet) mean on a Riemannian manifold.
Parameters¶
manifold : geomstats manifold A geomstats manifold instance with a metric. points : np.ndarray Array of shape (n_points, *point_shape) on the manifold. weights : np.ndarray or None Optional weights for the mean computation. max_iter : int Maximum iterations for gradient descent. tol : float Convergence tolerance.
Returns¶
np.ndarray The Karcher mean point on the manifold.
Source code in groupoid/manifold.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | |
Groupoid¶
groupoid.groupoid.Morphism
¶
Bases: BaseModel
A morphism in the transport groupoid.
Represents a transport map between two nodes (clients) in the federated learning network.
Source code in groupoid/groupoid.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
groupoid.groupoid.compose(f, g)
¶
Compose two morphisms f and g (f followed by g).
Requires f.target == g.source (category composition law).
Parameters¶
f : Morphism First morphism (applied first). g : Morphism Second morphism (applied second).
Returns¶
Morphism The composed morphism from f.source to g.target.
Raises¶
CompositionError If f.target != g.source.
Source code in groupoid/groupoid.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | |
groupoid.groupoid.inverse(f)
¶
Compute the inverse of a morphism.
Parameters¶
f : Morphism The morphism to invert.
Returns¶
Morphism The inverse morphism from f.target to f.source.
Source code in groupoid/groupoid.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | |
Cohomology¶
groupoid.cohomology.compute_h1(graph, transport_maps)
¶
Compute the H^1 cohomology norm of a transport cocycle.
Returns 0.0 (up to numerical tolerance) when the cocycle is a coboundary, meaning the local data is globally consistent.
The H^1 obstruction on a cycle is the deviation from the identity of
the holonomy, i.e. the ordered product of the restriction/transport
maps around the entire cycle. The cocycle must therefore be fully
specified: every edge of every basis cycle needs a transport map in
one direction or the other (the reverse direction is inverted). A
missing edge map leaves the holonomy undefined, so this function
raises :class:IncompleteCocycleError rather than silently forming a
partial product.
Parameters¶
graph : nx.DiGraph The groupoid nerve (directed graph of nodes/clients). transport_maps : dict Maps (source, target) edge tuples to transport matrices.
Returns¶
float The cohomology norm. Zero indicates global consistency.
Raises¶
IncompleteCocycleError If any edge on a basis cycle has no transport map in either direction, so the cycle's holonomy is undefined.
Source code in groupoid/cohomology.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | |
Sheaf¶
groupoid.sheaf.Sheaf
¶
A cellular sheaf on a graph.
Assigns vector spaces to nodes and linear restriction maps to edges.
Source code in groupoid/sheaf.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
get_restriction_map(source, target)
¶
Get the restriction map for an edge.
Source code in groupoid/sheaf.py
26 27 28 | |
get_section(node)
¶
Get the section value at a node.
Source code in groupoid/sheaf.py
34 35 36 | |
restrict(section, source, target)
¶
Apply the restriction map to a section.
Parameters¶
section : np.ndarray The section value at the source node. source : str Source node identifier. target : str Target node identifier.
Returns¶
np.ndarray The restricted section at the target node.
Source code in groupoid/sheaf.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | |
restrict_along_path(section, path)
¶
Restrict a section along a path of nodes.
Parameters¶
section : np.ndarray The section value at path[0]. path : list[str] Ordered list of nodes forming a path in the graph.
Returns¶
np.ndarray The section restricted to path[-1].
Source code in groupoid/sheaf.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
set_restriction_map(source, target, matrix)
¶
Set the restriction map for an edge.
Source code in groupoid/sheaf.py
21 22 23 24 | |
set_section(node, value)
¶
Set a section value at a node.
Source code in groupoid/sheaf.py
30 31 32 | |
Sheaf Laplacian¶
groupoid.laplacian.build_sheaf_laplacian(sheaf, stalk_dim)
¶
Build the sheaf Laplacian matrix.
For a sheaf F on graph G with n nodes and stalk dimension d, the sheaf Laplacian is a (nd) x (nd) block matrix defined as:
L_F = delta^T @ delta
where delta is the connection coboundary. For each edge (u, v) with restriction (transport) map R = R_{uv}: stalk(u) -> stalk(v), the coboundary acts as (delta x){(u,v)} = x_v - R{uv} x_u, so L = delta^T @ delta has blocks (summed over incident edges):
L[u,u] += R_{uv}^T @ R_{uv} (source diagonal)
L[v,v] += I (target diagonal)
L[u,v] += -R_{uv}^T (off-diagonal)
L[v,u] += -R_{uv} (off-diagonal)
L is symmetric positive semi-definite for ANY restriction maps (it is delta^T delta); its kernel is the space of transport-consistent global sections (x_v = R_{uv} x_u on every edge).
Parameters¶
sheaf A Sheaf instance with restriction maps set. stalk_dim Dimension of each stalk (vector space at each node).
Returns¶
np.ndarray The sheaf Laplacian matrix of shape (nd, nd).
Source code in groupoid/laplacian.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | |
groupoid.laplacian.spectral_analysis(sheaf, stalk_dim, tol=1e-10)
¶
Compute spectral decomposition of the sheaf Laplacian.
Parameters¶
sheaf A Sheaf instance with restriction maps. stalk_dim Dimension of each stalk. tol Tolerance for identifying zero eigenvalues.
Returns¶
SpectralSummary Full spectral summary including connectivity and consensus rate.
Source code in groupoid/laplacian.py
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | |
groupoid.laplacian.sheaf_diffusion_step(sheaf, sections, stalk_dim, step_size=0.1)
¶
One step of sheaf diffusion (Laplacian smoothing).
Drives local sections toward global consistency by flowing along the negative gradient of the sheaf Laplacian energy:
E(x) = x^T L_F x = sum_{(i,j)} ||R_{ij} x_i - x_j||^2
Parameters¶
sheaf Sheaf with restriction maps. sections Current section values at each node. stalk_dim Dimension of each stalk. step_size Diffusion step size (must be < 1/lambda_max for stability).
Returns¶
dict[str, np.ndarray] Updated section values after one diffusion step.
Source code in groupoid/laplacian.py
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | |
Parallel Transport¶
groupoid.transport.schild_ladder(manifold, tangent_vec, base_point, end_point, n_rungs=1)
¶
Parallel transport via Schild's ladder.
An iterative approximation of parallel transport that only requires
the exponential and logarithmic maps. This is the coarser of the two
ladders: on S^2 its direction agrees with the analytic parallel
transport only to cosine ~0.98 and does not converge to the exact
value as n_rungs increases (see pole_ladder for the accurate
variant and LIMITATIONS.md for the measured behavior).
Parameters¶
manifold A geomstats manifold with exp and log maps. tangent_vec Tangent vector at base_point to transport. base_point Starting point on the manifold. end_point Destination point on the manifold. n_rungs Number of ladder rungs (higher = more accurate).
Returns¶
np.ndarray The transported tangent vector at end_point.
Source code in groupoid/transport.py
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
groupoid.transport.pole_ladder(manifold, tangent_vec, base_point, end_point, n_rungs=1)
¶
Parallel transport via pole ladder.
A variant of Schild's ladder that uses geodesic symmetry instead of midpoint construction. More accurate than Schild's ladder for the same number of rungs, and exactly preserves the norm of the transported vector on symmetric spaces.
Parameters¶
manifold A geomstats manifold with exp and log maps. tangent_vec Tangent vector at base_point to transport. base_point Starting point on the manifold. end_point Destination point on the manifold. n_rungs Number of ladder rungs.
Returns¶
np.ndarray The transported tangent vector at end_point.
Source code in groupoid/transport.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | |
groupoid.transport.compute_transport_matrix(manifold, base_point, end_point, method='pole', n_rungs=2)
¶
Compute the parallel transport matrix between two points.
Constructs the full linear map T such that for any tangent vector v at base_point, T @ v gives the parallel transport of v to end_point.
Parameters¶
manifold A geomstats manifold. base_point Starting point on the manifold. end_point Destination point on the manifold. method Transport method: "pole" or "schild". n_rungs Number of ladder rungs for the approximation.
Returns¶
np.ndarray Transport matrix of shape (dim, dim).
Source code in groupoid/transport.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | |
Riemannian Optimizers¶
groupoid.optimizer.RiemannianSGD
dataclass
¶
Riemannian stochastic gradient descent.
Updates parameters by computing the Riemannian gradient (projection of Euclidean gradient onto tangent space) and retracting back to the manifold via the exponential map.
Parameters¶
manifold A geomstats manifold instance. lr Learning rate. momentum Momentum coefficient (0 = no momentum).
Source code in groupoid/optimizer.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
step(point, euclidean_grad)
¶
Perform one optimization step.
Parameters¶
point Current point on the manifold. euclidean_grad Euclidean gradient (will be projected to tangent space).
Returns¶
np.ndarray Updated point on the manifold.
Source code in groupoid/optimizer.py
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
groupoid.optimizer.RiemannianAdam
dataclass
¶
Riemannian Adam optimizer.
Adapts the Adam optimizer to Riemannian manifolds by maintaining exponential moving averages of the Riemannian gradient and its squared norm, with updates via the exponential map.
Parameters¶
manifold A geomstats manifold instance. lr Learning rate. beta1 Exponential decay rate for first moment. beta2 Exponential decay rate for second moment. eps Small constant for numerical stability.
Source code in groupoid/optimizer.py
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
step(point, euclidean_grad)
¶
Perform one optimization step.
Parameters¶
point Current point on the manifold. euclidean_grad Euclidean gradient.
Returns¶
np.ndarray Updated point on the manifold.
Source code in groupoid/optimizer.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
groupoid.optimizer.curvature_adaptive_lr(manifold, point, base_lr, tangent_vec)
¶
Adapt learning rate based on local sectional curvature.
In regions of high positive curvature, geodesics converge and we should take smaller steps. In regions of negative curvature, geodesics diverge and we can take larger steps.
Parameters¶
manifold A geomstats manifold with a curvature method. point Current point on the manifold. base_lr Base learning rate to adapt. tangent_vec Direction of the update.
Returns¶
float Adapted learning rate.
Source code in groupoid/optimizer.py
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
Persistent Homology¶
groupoid.persistence.compute_persistence(points, max_dim=1, max_edge_length=np.inf)
¶
Compute persistent homology of a point cloud.
Parameters¶
points Array of shape (n_points, n_features) representing model parameters or their embeddings. max_dim Maximum homological dimension to compute. max_edge_length Maximum edge length for the Rips filtration.
Returns¶
PersistenceSummary Topological summary including Betti numbers and persistence.
Source code in groupoid/persistence.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | |
groupoid.persistence.track_divergence(current_params, previous_summary=None, max_dim=1)
¶
Track federation divergence across rounds.
Computes persistence of current parameter distribution and, if a previous summary exists, computes the bottleneck distance to measure how much the topological structure has changed.
Parameters¶
current_params Array of shape (n_clients, n_features). previous_summary PersistenceSummary from the previous round, if available. max_dim Maximum homological dimension.
Returns¶
PersistenceSummary Updated summary with bottleneck distance to previous round.
Source code in groupoid/persistence.py
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | |