holonomy-lib 0.8.0__tar.gz

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.
Files changed (91) hide show
  1. holonomy_lib-0.8.0/LICENSE.md +105 -0
  2. holonomy_lib-0.8.0/PKG-INFO +161 -0
  3. holonomy_lib-0.8.0/README.md +119 -0
  4. holonomy_lib-0.8.0/pyproject.toml +107 -0
  5. holonomy_lib-0.8.0/setup.cfg +4 -0
  6. holonomy_lib-0.8.0/src/holonomy_explorer/__init__.py +1 -0
  7. holonomy_lib-0.8.0/src/holonomy_explorer/__main__.py +79 -0
  8. holonomy_lib-0.8.0/src/holonomy_explorer/batching.py +182 -0
  9. holonomy_lib-0.8.0/src/holonomy_explorer/common.py +187 -0
  10. holonomy_lib-0.8.0/src/holonomy_explorer/curvature.py +154 -0
  11. holonomy_lib-0.8.0/src/holonomy_explorer/datasets.py +346 -0
  12. holonomy_lib-0.8.0/src/holonomy_explorer/graphs.py +286 -0
  13. holonomy_lib-0.8.0/src/holonomy_explorer/server.py +172 -0
  14. holonomy_lib-0.8.0/src/holonomy_explorer/static/app.js +435 -0
  15. holonomy_lib-0.8.0/src/holonomy_explorer/static/charts.js +114 -0
  16. holonomy_lib-0.8.0/src/holonomy_explorer/static/index.html +45 -0
  17. holonomy_lib-0.8.0/src/holonomy_explorer/static/layout.js +85 -0
  18. holonomy_lib-0.8.0/src/holonomy_explorer/static/style.css +121 -0
  19. holonomy_lib-0.8.0/src/holonomy_explorer/static/view.js +195 -0
  20. holonomy_lib-0.8.0/src/holonomy_explorer/topology.py +118 -0
  21. holonomy_lib-0.8.0/src/holonomy_lib/__init__.py +9 -0
  22. holonomy_lib-0.8.0/src/holonomy_lib/_graph_utils.py +52 -0
  23. holonomy_lib-0.8.0/src/holonomy_lib/_quadrature.py +74 -0
  24. holonomy_lib-0.8.0/src/holonomy_lib/algebra/__init__.py +32 -0
  25. holonomy_lib-0.8.0/src/holonomy_lib/algebra/eigsh_sparse.py +251 -0
  26. holonomy_lib-0.8.0/src/holonomy_lib/algebra/lanczos.py +361 -0
  27. holonomy_lib-0.8.0/src/holonomy_lib/algebra/linear.py +180 -0
  28. holonomy_lib-0.8.0/src/holonomy_lib/algebra/solvers.py +547 -0
  29. holonomy_lib-0.8.0/src/holonomy_lib/convex/__init__.py +27 -0
  30. holonomy_lib-0.8.0/src/holonomy_lib/convex/least_squares.py +184 -0
  31. holonomy_lib-0.8.0/src/holonomy_lib/discrete_geometry/__init__.py +38 -0
  32. holonomy_lib-0.8.0/src/holonomy_lib/discrete_geometry/forman.py +242 -0
  33. holonomy_lib-0.8.0/src/holonomy_lib/discrete_geometry/ricci.py +855 -0
  34. holonomy_lib-0.8.0/src/holonomy_lib/experimental/__init__.py +13 -0
  35. holonomy_lib-0.8.0/src/holonomy_lib/experimental/heterogeneous_kappa.py +361 -0
  36. holonomy_lib-0.8.0/src/holonomy_lib/experimental/laplacian_eigenmaps.py +200 -0
  37. holonomy_lib-0.8.0/src/holonomy_lib/hyperbolic/__init__.py +27 -0
  38. holonomy_lib-0.8.0/src/holonomy_lib/hyperbolic/frechet_mean.py +381 -0
  39. holonomy_lib-0.8.0/src/holonomy_lib/hyperbolic/heat_kernel.py +608 -0
  40. holonomy_lib-0.8.0/src/holonomy_lib/hyperbolic/manifold_inner.py +81 -0
  41. holonomy_lib-0.8.0/src/holonomy_lib/info_geometry/__init__.py +64 -0
  42. holonomy_lib-0.8.0/src/holonomy_lib/info_geometry/divergences.py +224 -0
  43. holonomy_lib-0.8.0/src/holonomy_lib/info_geometry/fisher.py +179 -0
  44. holonomy_lib-0.8.0/src/holonomy_lib/lie/__init__.py +54 -0
  45. holonomy_lib-0.8.0/src/holonomy_lib/lie/so3.py +385 -0
  46. holonomy_lib-0.8.0/src/holonomy_lib/lie/spherical_harmonics.py +189 -0
  47. holonomy_lib-0.8.0/src/holonomy_lib/manifolds/__init__.py +53 -0
  48. holonomy_lib-0.8.0/src/holonomy_lib/manifolds/comparison.py +343 -0
  49. holonomy_lib-0.8.0/src/holonomy_lib/manifolds/fixed_rank.py +453 -0
  50. holonomy_lib-0.8.0/src/holonomy_lib/manifolds/lorentz.py +699 -0
  51. holonomy_lib-0.8.0/src/holonomy_lib/manifolds/lorentzian.py +567 -0
  52. holonomy_lib-0.8.0/src/holonomy_lib/manifolds/product.py +425 -0
  53. holonomy_lib-0.8.0/src/holonomy_lib/manifolds/spd.py +504 -0
  54. holonomy_lib-0.8.0/src/holonomy_lib/manifolds/stereographic.py +680 -0
  55. holonomy_lib-0.8.0/src/holonomy_lib/optimization/__init__.py +42 -0
  56. holonomy_lib-0.8.0/src/holonomy_lib/optimization/base.py +65 -0
  57. holonomy_lib-0.8.0/src/holonomy_lib/optimization/sgd.py +112 -0
  58. holonomy_lib-0.8.0/src/holonomy_lib/py.typed +0 -0
  59. holonomy_lib-0.8.0/src/holonomy_lib/sheaf/__init__.py +74 -0
  60. holonomy_lib-0.8.0/src/holonomy_lib/sheaf/graph_sheaf.py +352 -0
  61. holonomy_lib-0.8.0/src/holonomy_lib/sheaf/laplacian.py +529 -0
  62. holonomy_lib-0.8.0/src/holonomy_lib/simplicial/__init__.py +55 -0
  63. holonomy_lib-0.8.0/src/holonomy_lib/simplicial/_face_lookup.py +99 -0
  64. holonomy_lib-0.8.0/src/holonomy_lib/simplicial/complex.py +168 -0
  65. holonomy_lib-0.8.0/src/holonomy_lib/simplicial/sparse_complex.py +145 -0
  66. holonomy_lib-0.8.0/src/holonomy_lib/simplicial/vietoris_rips.py +277 -0
  67. holonomy_lib-0.8.0/src/holonomy_lib/spectral/__init__.py +55 -0
  68. holonomy_lib-0.8.0/src/holonomy_lib/spectral/diffusion_map.py +169 -0
  69. holonomy_lib-0.8.0/src/holonomy_lib/spectral/effective_resistance.py +199 -0
  70. holonomy_lib-0.8.0/src/holonomy_lib/spectral/embedding.py +131 -0
  71. holonomy_lib-0.8.0/src/holonomy_lib/spectral/heat_kernel.py +236 -0
  72. holonomy_lib-0.8.0/src/holonomy_lib/spectral/laplacian.py +441 -0
  73. holonomy_lib-0.8.0/src/holonomy_lib/spectral/magnetic.py +351 -0
  74. holonomy_lib-0.8.0/src/holonomy_lib/spectral/spectral_dimension.py +104 -0
  75. holonomy_lib-0.8.0/src/holonomy_lib/tensor_calculus/__init__.py +23 -0
  76. holonomy_lib-0.8.0/src/holonomy_lib/tensor_calculus/decomposition.py +208 -0
  77. holonomy_lib-0.8.0/src/holonomy_lib/topology/__init__.py +28 -0
  78. holonomy_lib-0.8.0/src/holonomy_lib/topology/_filtration.py +147 -0
  79. holonomy_lib-0.8.0/src/holonomy_lib/topology/_reduction.py +227 -0
  80. holonomy_lib-0.8.0/src/holonomy_lib/topology/hodge.py +250 -0
  81. holonomy_lib-0.8.0/src/holonomy_lib/topology/persistent_homology.py +301 -0
  82. holonomy_lib-0.8.0/src/holonomy_lib.egg-info/PKG-INFO +161 -0
  83. holonomy_lib-0.8.0/src/holonomy_lib.egg-info/SOURCES.txt +89 -0
  84. holonomy_lib-0.8.0/src/holonomy_lib.egg-info/dependency_links.txt +1 -0
  85. holonomy_lib-0.8.0/src/holonomy_lib.egg-info/entry_points.txt +2 -0
  86. holonomy_lib-0.8.0/src/holonomy_lib.egg-info/requires.txt +20 -0
  87. holonomy_lib-0.8.0/src/holonomy_lib.egg-info/top_level.txt +2 -0
  88. holonomy_lib-0.8.0/tests/test_audit.py +268 -0
  89. holonomy_lib-0.8.0/tests/test_conventions.py +103 -0
  90. holonomy_lib-0.8.0/tests/test_device_parity.py +194 -0
  91. holonomy_lib-0.8.0/tests/test_quadrature.py +47 -0
@@ -0,0 +1,105 @@
1
+ # Functional Source License, Version 1.1, ALv2 Future License
2
+
3
+ ## Abbreviation
4
+
5
+ FSL-1.1-ALv2
6
+
7
+ ## Notice
8
+
9
+ Copyright 2026 Synoros
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or
34
+ service that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software
39
+ that exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee
52
+ using the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to
59
+ the infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79
+ EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the Apache License, Version 2.0 that is effective on the second anniversary of
91
+ the date we make the Software available. On or after that date, you may use the
92
+ Software under the Apache License, Version 2.0, in which case the following
93
+ will apply:
94
+
95
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96
+ this file except in compliance with the License.
97
+
98
+ You may obtain a copy of the License at
99
+
100
+ http://www.apache.org/licenses/LICENSE-2.0
101
+
102
+ Unless required by applicable law or agreed to in writing, software distributed
103
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
+ specific language governing permissions and limitations under the License.
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.4
2
+ Name: holonomy-lib
3
+ Version: 0.8.0
4
+ Summary: Batched PyTorch primitives for Riemannian geometry, spectral graph theory, discrete curvature, topology, and tensor decompositions.
5
+ Author: Synoros
6
+ License-Expression: FSL-1.1-ALv2
7
+ Project-URL: Homepage, https://github.com/Synoros-io/holonomy_lib
8
+ Project-URL: Repository, https://github.com/Synoros-io/holonomy_lib
9
+ Project-URL: Issues, https://github.com/Synoros-io/holonomy_lib/issues
10
+ Keywords: pytorch,differential-geometry,riemannian-manifolds,hyperbolic-geometry,riemannian-optimization,spectral-graph-theory,graph-laplacian,magnetic-laplacian,heat-kernel,diffusion-maps,effective-resistance,ricci-curvature,ricci-flow,cellular-sheaves,simplicial-complex,hodge-laplacian,persistent-homology,topological-data-analysis,information-geometry,tensor-decomposition,numerical-linear-algebra
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Programming Language :: Python :: 3.14
18
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.12
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE.md
23
+ Requires-Dist: torch>=2.2
24
+ Requires-Dist: numpy>=1.26
25
+ Requires-Dist: scipy>=1.11.2
26
+ Provides-Extra: comparison
27
+ Requires-Dist: pymanopt; extra == "comparison"
28
+ Requires-Dist: geoopt; extra == "comparison"
29
+ Requires-Dist: geomstats; extra == "comparison"
30
+ Requires-Dist: autograd; extra == "comparison"
31
+ Requires-Dist: tensorly; extra == "comparison"
32
+ Requires-Dist: networkx; extra == "comparison"
33
+ Requires-Dist: gudhi; extra == "comparison"
34
+ Requires-Dist: ripser; extra == "comparison"
35
+ Requires-Dist: GraphRicciCurvature; extra == "comparison"
36
+ Provides-Extra: dev
37
+ Requires-Dist: pytest; extra == "dev"
38
+ Requires-Dist: ruff; extra == "dev"
39
+ Requires-Dist: mypy; extra == "dev"
40
+ Requires-Dist: scipy-stubs; extra == "dev"
41
+ Dynamic: license-file
42
+
43
+ # holonomy_lib
44
+
45
+ Geometry, graph and topology primitives for PyTorch. Most functions take a batch
46
+ of inputs (a leading batch dimension) and run on the device and dtype you pass in.
47
+
48
+ ## Install
49
+
50
+ Python 3.12 or later. Install PyTorch for your hardware first, using the
51
+ [PyTorch selector](https://pytorch.org/get-started/locally/), then:
52
+
53
+ ```bash
54
+ pip install holonomy-lib
55
+ ```
56
+
57
+ ## Example
58
+
59
+ Effective resistance between the ends of a three-node path and of a triangle,
60
+ computed as one batch:
61
+
62
+ ```python
63
+ import torch
64
+ from holonomy_lib.spectral import effective_resistance
65
+
66
+ device = "cuda" if torch.cuda.is_available() else "cpu" # ROCm builds also use "cuda"
67
+ adjacency = torch.tensor([
68
+ [[0, 1, 0], [1, 0, 1], [0, 1, 0]], # path 0-1-2
69
+ [[0, 1, 1], [1, 0, 1], [1, 1, 0]], # triangle
70
+ ], dtype=torch.float64, device=device)
71
+
72
+ R = effective_resistance(adjacency)
73
+ print(R.shape) # torch.Size([2, 3, 3])
74
+ print(R[:, 0, 2]) # tensor([2.0000, 0.6667], dtype=torch.float64)
75
+ ```
76
+
77
+ ## What's in it
78
+
79
+ [CONTENTS.md](https://github.com/Synoros-io/holonomy_lib/blob/master/CONTENTS.md) lists every function with its signature and the
80
+ paper it implements.
81
+
82
+ | Subpackage | Contents |
83
+ |---|---|
84
+ | `manifolds` | Fixed-rank, SPD, Lorentz, Lorentzian, stereographic and product manifolds; model-space volumes. |
85
+ | `optimization` | Riemannian SGD. |
86
+ | `hyperbolic` | Fréchet means, manifold-aware inner products, hyperbolic heat kernels. |
87
+ | `lie` | SO(3) exponential and logarithm, rotations, real spherical harmonics. |
88
+ | `info_geometry` | Bregman and KL divergences, Fisher information, natural gradients. |
89
+ | `tensor_calculus` | Mode unfolding, mode products, HOSVD. |
90
+ | `algebra` | Truncated SVD, dense and sparse eigensolvers, conjugate gradient, LSQR. |
91
+ | `convex` | Regularized least squares. |
92
+ | `spectral` | Graph Laplacians, embeddings, heat diffusion, effective resistance, spectral dimension. |
93
+ | `discrete_geometry` | Ollivier and Forman curvature, Ricci flow with surgery. |
94
+ | `sheaf` | Graph sheaves, coboundaries, sheaf Laplacians and their spectra. |
95
+ | `simplicial` | Dense and sparse simplicial complexes, boundary operators, Vietoris-Rips. |
96
+ | `topology` | Hodge Laplacians, Betti numbers, persistent homology. |
97
+
98
+ ## Explorer
99
+
100
+ `holonomy-explorer` opens a local page that runs the library live: curvature
101
+ and diffusion on graphs, geodesics as curvature passes through zero,
102
+ persistent homology of point clouds, and batch-size timings on your hardware.
103
+ Options: `--device`, `--dtype`, `--port`, `--no-browser`.
104
+
105
+ ![The explorer's graph view](https://raw.githubusercontent.com/Synoros-io/holonomy_lib/master/docs/explorer.png)
106
+
107
+ ## Experimental
108
+
109
+ `holonomy_lib.experimental` holds two unfinished pieces that are not part of
110
+ the stable API:
111
+
112
+ - `hyperbolic_laplacian_eigenmaps`: nothing in its objective keeps nodes apart,
113
+ so an embedding can collapse to a point.
114
+ - `HeterogeneousKappaManifold`: a curvature per point. Its `dissimilarity` is
115
+ not a metric.
116
+
117
+ ## Limits
118
+
119
+ - Use `float64` when accuracy matters.
120
+ - Sparse eigensolvers, sparse simplicial complexes and sheaves handle one
121
+ instance at a time. Sparse eigensolvers are not differentiable.
122
+ - Persistent homology runs its reduction one batch member at a time on the CPU.
123
+ - Ollivier curvature uses entropy-regularized transport, so it is close to the
124
+ exact value rather than equal to it, and it warns if the solver did not
125
+ converge. Edge weights act as both lengths and random-walk weights.
126
+ - Gradients through `cg` can be wrong when it converges in very few iterations.
127
+ - Effective resistance and commute time are `inf` between disconnected components.
128
+
129
+ ## Development
130
+
131
+ ```bash
132
+ uv sync --extra dev
133
+ python -m pytest -q
134
+ python -m ruff check src/ tests/
135
+ python -m mypy src/
136
+ python tools/audit.py src/holonomy_lib --strict
137
+ ```
138
+
139
+ [CONVENTIONS.md](https://github.com/Synoros-io/holonomy_lib/blob/master/CONVENTIONS.md) has the coding and numerical rules;
140
+ [CHANGELOG.md](https://github.com/Synoros-io/holonomy_lib/blob/master/CHANGELOG.md) has the release history.
141
+
142
+ ## Citation
143
+
144
+ ```bibtex
145
+ @software{holonomy_lib,
146
+ author = {John Vaught},
147
+ title = {holonomy\_lib: Batched PyTorch primitives for geometry and topology},
148
+ version = {0.8.0},
149
+ year = {2026},
150
+ url = {https://github.com/Synoros-io/holonomy_lib},
151
+ }
152
+ ```
153
+
154
+ Please also cite the papers named in the docstrings of the functions you use.
155
+
156
+ ## License
157
+
158
+ [FSL-1.1-ALv2](https://github.com/Synoros-io/holonomy_lib/blob/master/LICENSE.md). You can use and modify it freely; competing
159
+ commercial use is reserved to Synoros. Each release becomes Apache-2.0 two
160
+ years after it ships. Releases up to 0.7.0 remain AGPL-3.0-or-later. For other
161
+ terms, contact [contact@synoros.io](mailto:contact@synoros.io).
@@ -0,0 +1,119 @@
1
+ # holonomy_lib
2
+
3
+ Geometry, graph and topology primitives for PyTorch. Most functions take a batch
4
+ of inputs (a leading batch dimension) and run on the device and dtype you pass in.
5
+
6
+ ## Install
7
+
8
+ Python 3.12 or later. Install PyTorch for your hardware first, using the
9
+ [PyTorch selector](https://pytorch.org/get-started/locally/), then:
10
+
11
+ ```bash
12
+ pip install holonomy-lib
13
+ ```
14
+
15
+ ## Example
16
+
17
+ Effective resistance between the ends of a three-node path and of a triangle,
18
+ computed as one batch:
19
+
20
+ ```python
21
+ import torch
22
+ from holonomy_lib.spectral import effective_resistance
23
+
24
+ device = "cuda" if torch.cuda.is_available() else "cpu" # ROCm builds also use "cuda"
25
+ adjacency = torch.tensor([
26
+ [[0, 1, 0], [1, 0, 1], [0, 1, 0]], # path 0-1-2
27
+ [[0, 1, 1], [1, 0, 1], [1, 1, 0]], # triangle
28
+ ], dtype=torch.float64, device=device)
29
+
30
+ R = effective_resistance(adjacency)
31
+ print(R.shape) # torch.Size([2, 3, 3])
32
+ print(R[:, 0, 2]) # tensor([2.0000, 0.6667], dtype=torch.float64)
33
+ ```
34
+
35
+ ## What's in it
36
+
37
+ [CONTENTS.md](https://github.com/Synoros-io/holonomy_lib/blob/master/CONTENTS.md) lists every function with its signature and the
38
+ paper it implements.
39
+
40
+ | Subpackage | Contents |
41
+ |---|---|
42
+ | `manifolds` | Fixed-rank, SPD, Lorentz, Lorentzian, stereographic and product manifolds; model-space volumes. |
43
+ | `optimization` | Riemannian SGD. |
44
+ | `hyperbolic` | Fréchet means, manifold-aware inner products, hyperbolic heat kernels. |
45
+ | `lie` | SO(3) exponential and logarithm, rotations, real spherical harmonics. |
46
+ | `info_geometry` | Bregman and KL divergences, Fisher information, natural gradients. |
47
+ | `tensor_calculus` | Mode unfolding, mode products, HOSVD. |
48
+ | `algebra` | Truncated SVD, dense and sparse eigensolvers, conjugate gradient, LSQR. |
49
+ | `convex` | Regularized least squares. |
50
+ | `spectral` | Graph Laplacians, embeddings, heat diffusion, effective resistance, spectral dimension. |
51
+ | `discrete_geometry` | Ollivier and Forman curvature, Ricci flow with surgery. |
52
+ | `sheaf` | Graph sheaves, coboundaries, sheaf Laplacians and their spectra. |
53
+ | `simplicial` | Dense and sparse simplicial complexes, boundary operators, Vietoris-Rips. |
54
+ | `topology` | Hodge Laplacians, Betti numbers, persistent homology. |
55
+
56
+ ## Explorer
57
+
58
+ `holonomy-explorer` opens a local page that runs the library live: curvature
59
+ and diffusion on graphs, geodesics as curvature passes through zero,
60
+ persistent homology of point clouds, and batch-size timings on your hardware.
61
+ Options: `--device`, `--dtype`, `--port`, `--no-browser`.
62
+
63
+ ![The explorer's graph view](https://raw.githubusercontent.com/Synoros-io/holonomy_lib/master/docs/explorer.png)
64
+
65
+ ## Experimental
66
+
67
+ `holonomy_lib.experimental` holds two unfinished pieces that are not part of
68
+ the stable API:
69
+
70
+ - `hyperbolic_laplacian_eigenmaps`: nothing in its objective keeps nodes apart,
71
+ so an embedding can collapse to a point.
72
+ - `HeterogeneousKappaManifold`: a curvature per point. Its `dissimilarity` is
73
+ not a metric.
74
+
75
+ ## Limits
76
+
77
+ - Use `float64` when accuracy matters.
78
+ - Sparse eigensolvers, sparse simplicial complexes and sheaves handle one
79
+ instance at a time. Sparse eigensolvers are not differentiable.
80
+ - Persistent homology runs its reduction one batch member at a time on the CPU.
81
+ - Ollivier curvature uses entropy-regularized transport, so it is close to the
82
+ exact value rather than equal to it, and it warns if the solver did not
83
+ converge. Edge weights act as both lengths and random-walk weights.
84
+ - Gradients through `cg` can be wrong when it converges in very few iterations.
85
+ - Effective resistance and commute time are `inf` between disconnected components.
86
+
87
+ ## Development
88
+
89
+ ```bash
90
+ uv sync --extra dev
91
+ python -m pytest -q
92
+ python -m ruff check src/ tests/
93
+ python -m mypy src/
94
+ python tools/audit.py src/holonomy_lib --strict
95
+ ```
96
+
97
+ [CONVENTIONS.md](https://github.com/Synoros-io/holonomy_lib/blob/master/CONVENTIONS.md) has the coding and numerical rules;
98
+ [CHANGELOG.md](https://github.com/Synoros-io/holonomy_lib/blob/master/CHANGELOG.md) has the release history.
99
+
100
+ ## Citation
101
+
102
+ ```bibtex
103
+ @software{holonomy_lib,
104
+ author = {John Vaught},
105
+ title = {holonomy\_lib: Batched PyTorch primitives for geometry and topology},
106
+ version = {0.8.0},
107
+ year = {2026},
108
+ url = {https://github.com/Synoros-io/holonomy_lib},
109
+ }
110
+ ```
111
+
112
+ Please also cite the papers named in the docstrings of the functions you use.
113
+
114
+ ## License
115
+
116
+ [FSL-1.1-ALv2](https://github.com/Synoros-io/holonomy_lib/blob/master/LICENSE.md). You can use and modify it freely; competing
117
+ commercial use is reserved to Synoros. Each release becomes Apache-2.0 two
118
+ years after it ships. Releases up to 0.7.0 remain AGPL-3.0-or-later. For other
119
+ terms, contact [contact@synoros.io](mailto:contact@synoros.io).
@@ -0,0 +1,107 @@
1
+ [project]
2
+ name = "holonomy-lib"
3
+ version = "0.8.0"
4
+ description = "Batched PyTorch primitives for Riemannian geometry, spectral graph theory, discrete curvature, topology, and tensor decompositions."
5
+ readme = "README.md"
6
+ license = "FSL-1.1-ALv2"
7
+ license-files = ["LICENSE.md"]
8
+ authors = [{ name = "Synoros" }]
9
+ requires-python = ">=3.12"
10
+ keywords = [
11
+ "pytorch",
12
+ "differential-geometry",
13
+ "riemannian-manifolds",
14
+ "hyperbolic-geometry",
15
+ "riemannian-optimization",
16
+ "spectral-graph-theory",
17
+ "graph-laplacian",
18
+ "magnetic-laplacian",
19
+ "heat-kernel",
20
+ "diffusion-maps",
21
+ "effective-resistance",
22
+ "ricci-curvature",
23
+ "ricci-flow",
24
+ "cellular-sheaves",
25
+ "simplicial-complex",
26
+ "hodge-laplacian",
27
+ "persistent-homology",
28
+ "topological-data-analysis",
29
+ "information-geometry",
30
+ "tensor-decomposition",
31
+ "numerical-linear-algebra",
32
+ ]
33
+ classifiers = [
34
+ "Development Status :: 4 - Beta",
35
+ "Intended Audience :: Science/Research",
36
+ "Operating System :: OS Independent",
37
+ "Programming Language :: Python :: 3 :: Only",
38
+ "Programming Language :: Python :: 3.12",
39
+ "Programming Language :: Python :: 3.13",
40
+ "Programming Language :: Python :: 3.14",
41
+ "Topic :: Scientific/Engineering :: Mathematics",
42
+ "Typing :: Typed",
43
+ ]
44
+
45
+ # The floors are the first releases that ship Python 3.12 wheels; nothing in
46
+ # the source needs anything newer. torch decides the hardware: pip picks the
47
+ # default CUDA wheel, so for ROCm, a specific CUDA version or CPU-only, install
48
+ # torch first from https://pytorch.org/get-started/locally/ and pip will keep it.
49
+ dependencies = [
50
+ "torch>=2.2",
51
+ "numpy>=1.26",
52
+ "scipy>=1.11.2",
53
+ ]
54
+
55
+ [project.urls]
56
+ Homepage = "https://github.com/Synoros-io/holonomy_lib"
57
+ Repository = "https://github.com/Synoros-io/holonomy_lib"
58
+ Issues = "https://github.com/Synoros-io/holonomy_lib/issues"
59
+
60
+ [project.scripts]
61
+ holonomy-explorer = "holonomy_explorer.__main__:main"
62
+
63
+ [tool.setuptools.package-data]
64
+ holonomy_explorer = ["static/*"]
65
+
66
+ [project.optional-dependencies]
67
+ # Libraries the cross-check tests compare against. None of them are needed at
68
+ # runtime; each comparison test skips itself when its library is missing.
69
+ comparison = [
70
+ "pymanopt",
71
+ "geoopt",
72
+ "geomstats",
73
+ "autograd",
74
+ "tensorly",
75
+ "networkx",
76
+ "gudhi",
77
+ "ripser",
78
+ "GraphRicciCurvature",
79
+ ]
80
+
81
+ # Development toolchain: tests, lint, type checks (with SciPy's stubs so mypy
82
+ # can see through the sparse and quadrature fallbacks).
83
+ dev = ["pytest", "ruff", "mypy", "scipy-stubs"]
84
+
85
+ [build-system]
86
+ requires = ["setuptools>=77"]
87
+ build-backend = "setuptools.build_meta"
88
+
89
+ [tool.setuptools.packages.find]
90
+ where = ["src"]
91
+
92
+ [tool.pytest.ini_options]
93
+ testpaths = ["tests"]
94
+
95
+ [tool.ruff]
96
+ target-version = "py312"
97
+ extend-exclude = [".scratch", "archive", "notes"]
98
+
99
+ [tool.ruff.lint]
100
+ select = ["E", "F", "W", "I", "UP", "B"]
101
+
102
+ [tool.mypy]
103
+ python_version = "3.12"
104
+ files = ["src"]
105
+ check_untyped_defs = true
106
+ warn_unused_ignores = true
107
+ warn_redundant_casts = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ """Local, offline views of computations performed by holonomy_lib."""
@@ -0,0 +1,79 @@
1
+ """Launch with holonomy-explorer or python -m holonomy_explorer."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import os
7
+ import webbrowser
8
+
9
+ import torch
10
+
11
+ from .common import Context
12
+ from .server import create_server
13
+
14
+ # Local-only defaults requested by the explorer brief; every deployment can override.
15
+ DEFAULT_HOST = "127.0.0.1"
16
+ WILDCARD_HOST = "0.0.0.0" # IPv4 bind-all address; browse via loopback instead.
17
+ DEFAULT_PORT = 8765
18
+ DEFAULT_DTYPE = "float64"
19
+ MAX_PORT = 65535 # TCP port field is an unsigned 16-bit integer.
20
+
21
+
22
+ def main() -> None:
23
+ """Parse deployment settings, print the bound URL, and serve until Ctrl-C."""
24
+ parser = argparse.ArgumentParser(
25
+ description="Local holonomy_lib explorer. Offline UI; CPU/CUDA tensors.",
26
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
27
+ )
28
+ parser.add_argument(
29
+ "--host",
30
+ default=os.getenv("HOLONOMY_EXPLORER_HOST", DEFAULT_HOST),
31
+ help="bind address; env HOLONOMY_EXPLORER_HOST",
32
+ )
33
+ parser.add_argument(
34
+ "--port",
35
+ type=int,
36
+ default=os.getenv("HOLONOMY_EXPLORER_PORT", str(DEFAULT_PORT)),
37
+ help="TCP port, 0 chooses a free port; env HOLONOMY_EXPLORER_PORT",
38
+ )
39
+ parser.add_argument(
40
+ "--device",
41
+ default=os.getenv(
42
+ "HOLONOMY_EXPLORER_DEVICE",
43
+ "cuda" if torch.cuda.is_available() else "cpu",
44
+ ),
45
+ help="torch device; env HOLONOMY_EXPLORER_DEVICE; ROCm also uses cuda",
46
+ )
47
+ parser.add_argument(
48
+ "--dtype",
49
+ choices=("float32", "float64"),
50
+ default=os.getenv("HOLONOMY_EXPLORER_DTYPE", DEFAULT_DTYPE),
51
+ help="tensor precision; env HOLONOMY_EXPLORER_DTYPE",
52
+ )
53
+ parser.add_argument(
54
+ "--no-browser", action="store_true", help="print URL without opening a browser"
55
+ )
56
+ args = parser.parse_args()
57
+ if not 0 <= args.port <= MAX_PORT:
58
+ parser.error(f"port must be between 0 and {MAX_PORT}")
59
+ try:
60
+ context = Context.from_request({"device": args.device, "dtype": args.dtype})
61
+ server = create_server(args.host, args.port, str(context.device), args.dtype)
62
+ except (OSError, ValueError, RuntimeError) as error:
63
+ parser.error(str(error))
64
+ # Wildcard bindings are not navigable destinations; loopback reaches this server.
65
+ browser_host = DEFAULT_HOST if args.host == WILDCARD_HOST else args.host
66
+ url = f"http://{browser_host}:{server.server_address[1]}"
67
+ print(f"Holonomy explorer: {url} ({context.device}, {args.dtype})", flush=True)
68
+ if not args.no_browser:
69
+ webbrowser.open(url)
70
+ try:
71
+ server.serve_forever()
72
+ except KeyboardInterrupt:
73
+ pass
74
+ finally:
75
+ server.server_close()
76
+
77
+
78
+ if __name__ == "__main__":
79
+ main()