Ricci Curvature for Software Architecture Analysis
1. Introduction
Software systems, once they exceed a modest size, develop structural problems that are invisible from any single file. Dependency cycles emerge gradually, god-modules absorb responsibility, and bridge files silently become single points of failure. Traditional metrics — cyclomatic complexity, lines of code, fan-in/fan-out — capture local properties but miss the global geometry of how modules relate to each other.
Ricci curvature, a concept from differential geometry, measures how space curves by comparing the distance between nearby geodesics. On a sphere (positive curvature), geodesics converge; on a saddle (negative curvature), they diverge. This same idea transfers to graphs: an edge connecting two tightly-knit clusters has positive curvature, while an edge bridging two otherwise disconnected regions has negative curvature.
This article describes how arxo applies discrete Ricci curvature to dependency graphs — treating files as nodes and imports as edges — to diagnose architectural health, detect singularity patterns, and recommend targeted refactoring.
2. Background: Curvature on Graphs
2.1 The Dependency Graph
The input is a directed weighted graph ( G = (V, E, w) ) where:
- Nodes ( V ) are source files (or modules)
- Edges ( E ) are import dependencies (
import,require,re-export, etc.) - Weights ( w(e) ) are derived from edge type (e.g., dynamic imports carry lower weight than static imports)
The graph is extracted by parsing source code and resolving import paths, producing a petgraph::Graph<NodeMetadata, EdgeData, Directed>.
2.2 Three Curvature Variants
Arxo computes three complementary curvature measures, each with different trade-offs between speed and accuracy.
Augmented Forman-Ricci Curvature (FRC)
The primary metric, based on Sreejith et al. (2016). For an edge ( e = (u, v) ):
[ F(e) = 4 - \deg(u) - \deg(v) + \lambda \cdot \Delta(e) ]
where ( \deg(\cdot) ) is the undirected degree (in + out neighbors), ( \Delta(e) ) counts triangles through the edge, and ( \lambda = 3 ) is a parameter chosen so that the FRC distribution best approximates Ollivier-Ricci on scale-free networks.
Complexity: ( O(|E| \cdot d_{\max}^2) ) — fast enough for the default computation path.
Intuition: High-degree endpoints without triangles produce strongly negative curvature. Triangles “heal” the curvature, reflecting redundant paths that reduce fragility.
Ollivier-Ricci Curvature (ORC)
The more mathematically principled variant, using optimal transport. For each node ( u ), define a probability measure on its neighborhood:
[ m_u(k) = \alpha \cdot \delta_{u,k} + (1 - \alpha) \cdot \frac{w(u,k)}{\sum_j w(u,j)} ]
where ( \alpha \in [0, 1] ) is an idleness parameter (probability of staying at ( u )). The curvature of edge ( (u, v) ) is:
[ \kappa(u, v) = 1 - \frac{W_1(m_u, m_v)}{d(u, v)} ]
where ( W_1 ) is the Wasserstein-1 (Earth Mover’s) distance. Arxo computes ORC at four alpha values simultaneously (0.3, 0.5, 0.7, and a user-configured value) to assess sensitivity.
Complexity: ( O(|E| \cdot d_{\max}^3) ) — 10-100× slower than FRC, but tractable for software graphs where ( d_{\max} < 50 ).
Bakry-Émery Curvature
A vertex-based curvature derived from the curvature-dimension inequality ( CD(K, N) ) (Bakry & Émery, 1985). Unlike Forman and Ollivier (which are edge-based), Bakry-Émery assigns curvature to nodes using local clustering coefficient and degree. Edge curvatures are obtained by averaging endpoint values. Computed with dimension parameter ( N = \infty ) by default.
2.3 Interpreting Curvature Values
| Curvature | Geometric Analogy | Software Meaning |
|---|---|---|
| Negative | Saddle / hyperbolic — geodesics diverge | Bridge between clusters. Architectural bottleneck. Single point of failure. |
| Zero | Flat / Euclidean — geodesics parallel | Balanced connection. Neither bridge nor redundant. |
| Positive | Sphere — geodesics converge | Within a cohesive module. Redundant paths exist. Healthy structure. |
3. Aggregate Health Metrics
Raw per-edge curvature values are aggregated into scalar metrics that summarize the architectural health of an entire codebase.
3.1 Negative Curvature Share
[ \text{neg_share} = \frac{|{e \in E : \kappa(e) < 0}|}{|E|} ]
The fraction of edges with negative curvature. Interpretation thresholds:
- < 10% — Healthy boundaries. Most dependencies stay within well-structured modules.
- 10–30% — Mixed structure. Some cross-cutting concerns or legacy bridges.
- > 30% — Systematic architectural problems. The graph is dominated by bottleneck connections.
3.2 Bridge Mass
[ \text{bridge_mass} = \frac{1}{|E^-|} \sum_{e \in E^-} |\kappa(e)| ]
The mean absolute curvature of negative-curvature edges. When bridge_mass > 0.08, the architecture is held together by a few critical bridges — structurally fragile.
3.3 Hotspot Concentration
[ \text{hotspot_conc} = \frac{\sum_{v \in \text{top-5%}} |\kappa_v|}{\sum_{v \in V} |\kappa_v|} ]
The fraction of total negative curvature concentrated in the top 5% of nodes. When hotspot_conc > 0.50, half of all bridge pain is localized in a small set of files — these are actionable refactoring targets.
4. Singularity Patterns
Inspired by Perelman’s classification of singularities in Ricci flow (though adapted as an engineering taxonomy, not a strict mathematical correspondence), arxo detects five canonical neighborhood (CN) patterns.
CN-1: Neck (Bridge)
Detection: Edge has FRC ( < -0.3 ) AND edge betweenness ( > p_{95} ).
A neck is an edge that, if removed, would significantly increase the shortest paths between the components it connects. These are the load-bearing walls of the dependency graph.
Surgery: Extract an interface (ports.ts) or apply the Dependency Inversion Principle to decouple the modules.
CN-2: Knot (Cycle)
Detection: Edge belongs to a strongly connected component (SCC) with 2–5 nodes.
Knots are tight bidirectional dependency cycles. They make it impossible to build, test, or reason about any member of the cycle in isolation.
Surgery: Extract shared types into a separate types.ts file without back-imports. Remove barrel exports (index.ts) that induce artificial cycles.
CN-3: Cap (Dead End)
Detection: Low-degree terminal leaf violating intended layer boundaries.
Caps are leaf modules that import from layers they shouldn’t reach — a UI component importing directly from the database layer, for instance.
Surgery: Add an adapter layer that mediates the dependency.
CN-4: Horn (Tendril)
Detection: Node on a chain of length ( > 5 ) with low clustering coefficient.
Horns are long, thin chains of single-purpose helper files. Each link in the chain has only one consumer and one dependency, creating a fragile pipeline.
Surgery: Collapse the chain into a single module or introduce a facade.
CN-5: Hub (God Module)
Detection: Degree ( > p_{95} ) AND high incident negative curvature.
Hubs are files that everything depends on — utils.ts, shared/index.ts, helpers.ts. They accumulate responsibilities over time and become impossible to modify without cascading effects.
Surgery: Split by domain (e.g., shared/date.ts, shared/http.ts, shared/format.ts).
Singularity Shape Taxonomy
Each canonical pattern maps to a singularity shape, drawing loose inspiration from Perelman’s ancient solutions:
| Pattern | Shape | Analogy |
|---|---|---|
| CN-5 Hub | Hub-like | Round (central collapse) |
| CN-1 Neck, CN-4 Horn | Chain-like | Cylinder (linear neck) |
| CN-3 Cap | Dead-end-like | Bryant soliton (cusp) |
| CN-2 Knot | Growing-coupling-like | Gradient shrinking (expanding interdependence) |
5. Singularity Scoring
Individual patterns gain priority through a composite singularity score that fuses three orthogonal signals:
[ S(e) = z(-\kappa(e)) + z(\text{betweenness}(e)) + z(\Delta\text{coupling}(e)) ]
where ( z(\cdot) ) denotes z-score normalization. The three components capture:
- Geometric anomaly — negative curvature measures how much an edge behaves as a bridge.
- Structural bottleneck — edge betweenness centrality counts shortest paths through the edge.
- Evolutionary coupling — git co-change frequency reveals dependencies the static graph doesn’t capture.
Interpretation:
- ( S > 2.0 ) — Critical singularity requiring immediate attention.
- ( 1.0 < S \leq 2.0 ) — Significant issue worth investigating.
- ( S \leq 1.0 ) — Normal.
Surgery priorities are adjusted as: priority = 0.5 × severity + 0.5 × singularity_composite.
6. Ricci Flow on Dependency Graphs
Beyond static curvature measurement, arxo simulates discrete Ricci flow — the same process that powered Perelman’s proof of the Poincaré conjecture, adapted to graphs.
At each iteration, edge weights evolve as:
[ w’(e) = w(e) \cdot \exp(-\eta \cdot \kappa(e)) ]
where ( \eta ) is the step size (default 0.1). Edges with negative curvature (bridges) gain weight, while edges with positive curvature (intra-cluster) lose weight. Over iterations, the graph’s community structure becomes increasingly pronounced.
Two flow-derived metrics are tracked:
- Energy drop ( = (E_0 - E_T) / E_0 ) — the fractional reduction in curvature variance. Higher values indicate the flow successfully separated communities.
- Time to separation — the number of iterations until curvature variance stabilizes. Faster separation suggests clearer pre-existing boundaries.
Perelman’s W-Functional
Arxo computes a discrete approximation of Perelman’s W-functional (entropy):
[ W(g, f, \tau) = \int \left[\tau(|\nabla f|^2 + R) + f - n\right] (4\pi\tau)^{-n/2} e^{-f} , dV ]
In the continuous setting, ( W ) is monotonically non-decreasing along Ricci flow. For engineering use, arxo inverts the sign: the disorder score ( = -W ) decreases as architecture improves. This provides an entropy-like measure that can be tracked over time and gated in CI.
7. Defect Prediction
Curvature alone predicts defect-prone dependencies. An interaction model of curvature and degree achieves the best empirical performance:
[ \text{logit}(p) = \beta_0 + \beta_1 \cdot \kappa + \beta_2 \cdot d + \beta_3 \cdot (\kappa \times d) ]
Trained on 23,366 edges, this model achieves AUC 0.699 (+6.9% over a degree-only baseline). The interaction term captures that curvature’s signal is strongest for low-degree edges — a bridge between two small modules is more defect-prone than a bridge between two large clusters, because the latter has alternative paths.
Risk categories:
- Low risk: score < 0.3
- Medium risk: 0.3 ≤ score < 0.6
- Critical risk: score ≥ 0.6
- Flag for review: score ≥ 0.293 (research-validated threshold optimizing recall)
8. Practical Application
What to look at first
frc_neg_share— If above 30%, the codebase has structural problems at scale.- Top singularity scores — Sort edges by composite ( S(e) ) to find the highest-priority refactoring targets.
- CN pattern counts — Knots (CN-2) and hubs (CN-5) are the most common sources of developer pain.
- Flow energy drop — If Ricci flow produces a large energy drop, the codebase has clear latent modules that the current dependency structure doesn’t respect.
What curvature does NOT measure
Curvature is a topological metric. It captures the shape of dependencies, not:
- Runtime performance (use profiling)
- Code quality within a file (use complexity metrics)
- Business logic correctness (use tests)
- API design quality (use contract testing)
It is most valuable as a complement to these approaches, providing the architectural layer that local metrics miss.
9. References
- Ollivier, Y. (2009). “Ricci curvature of Markov chains on metric spaces.” Journal of Functional Analysis, 256(3), 810–864.
- Sreejith, R. P., Mohanraj, K., Jost, J., Saucan, E., & Samal, A. (2016). “Forman curvature for complex networks.” Journal of Statistical Mechanics, 063206.
- Bakry, D. & Émery, M. (1985). “Diffusions hypercontractives.” Séminaire de probabilités XIX, Springer, 177–206.
- Ni, C.-C., Lin, Y.-Y., Gao, J., Gu, X. D., & Saucan, E. (2015). “Ricci curvature of the Internet topology.” IEEE INFOCOM, 2758–2766.
- Perelman, G. (2002). “The entropy formula for the Ricci flow and its geometric applications.” arXiv:math/0211159.
- Samal, A., Sreejith, R. P., Gu, J., Liu, S., Saucan, E., & Jost, J. (2018). “Comparative analysis of two discretizations of Ricci curvature for complex networks.” Scientific Reports, 8, 8650.