Skip to content

Commit 0b6c59d

Browse files
committed
Update readme/contributing; fix clustering tests
1 parent 63dc17f commit 0b6c59d

File tree

3 files changed

+110
-14
lines changed

3 files changed

+110
-14
lines changed

CONTRIBUTING.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Contributing to Manify
2+
3+
Thank you for your interest in contributing to Manify! We welcome contributions of all kinds.
4+
5+
## Getting Started
6+
7+
1. **Fork and clone** the repository
8+
2. **Install in development mode**:
9+
```bash
10+
pip install -e ".[dev]"
11+
```
12+
3. **Set up pre-commit hooks**:
13+
```bash
14+
pre-commit install
15+
```
16+
17+
## Code Quality Standards
18+
19+
### Type Annotations
20+
- Use type annotations for all functions and methods
21+
- Use `jaxtyping` for tensor shape annotations:
22+
```python
23+
from jaxtyping import Float
24+
import torch
25+
26+
def process_embeddings(x: Float[torch.Tensor, "batch dim"]) -> Float[torch.Tensor, "batch output_dim"]:
27+
...
28+
```
29+
30+
### Testing
31+
- Write unit tests for all new functionality
32+
- **Coverage requirement**: 80%+ for new code
33+
- Run tests with beartype enabled (as in CI):
34+
```bash
35+
pytest tests --cov
36+
```
37+
- Tests should cover edge cases and error conditions
38+
39+
### Code Style
40+
- We use **Ruff** for linting and formatting
41+
- Check your code before committing:
42+
```bash
43+
ruff check manify/
44+
ruff format manify/
45+
```
46+
- Type check with MyPy:
47+
```bash
48+
mypy manify/
49+
```
50+
51+
## Documentation
52+
53+
We especially welcome documentation contributions! Areas where help is needed:
54+
55+
- **Mathematical details**: The [paper](https://arxiv.org/abs/2503.09576) contains rich mathematical content that could be integrated into the docs
56+
- **Tutorials**: More examples and tutorials are always appreciated
57+
- **API documentation**: Improving docstrings and examples
58+
- **Use case guides**: Real-world applications and workflows
59+
60+
Documentation uses Google-style docstrings:
61+
```python
62+
def my_function(param1: int, param2: str) -> bool:
63+
"""Brief description of the function.
64+
65+
Args:
66+
param1: Description of param1
67+
param2: Description of param2
68+
69+
Returns:
70+
Description of return value
71+
72+
Raises:
73+
ValueError: When something goes wrong
74+
"""
75+
```
76+
77+
## Pull Request Process
78+
79+
1. **Create a feature branch** from `main`
80+
2. **Make your changes** following the standards above
81+
3. **Add tests** with good coverage
82+
4. **Update documentation** as needed
83+
5. **Ensure CI passes** (tests, linting, type checking)
84+
6. **Submit a pull request** with a clear description
85+
86+
## Questions?
87+
88+
- Open an [issue](https://github.com/pchlenski/manify/issues) for bugs or feature requests
89+
- Start a [discussion](https://github.com/pchlenski/manify/discussions) for questions
90+
91+
We appreciate your contributions to making non-Euclidean machine learning more accessible!

README.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@
88
[![codecov](https://codecov.io/gh/pchlenski/manify/branch/main/graph/badge.svg)](https://codecov.io/gh/pchlenski/manify)
99
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
1010

11-
12-
Manify is a Python library for generating graph/data embeddings and performing machine learning in product spaces with mixed curvature (hyperbolic, Euclidean, and spherical spaces). It provides tools for manifold creation, curvature estimation, embedding generation, and predictive modeling that respects the underlying geometry of complex data.
13-
14-
You can read our manuscript here: [Manify: A Python Library for Learning Non-Euclidean Representations](https://arxiv.org/abs/2503.09576)
11+
Manify is a Python library for non-Euclidean representation learning.
12+
It is built on top of `geoopt` and follows `scikit-learn` API conventions.
13+
The library supports a variety of workflows involving (products of) Riemannian manifolds, including:
14+
- All basic manifold operations (e.g. exponential map, logarithmic map, parallel transport, and distance computations)
15+
- Sampling Gaussian distributions and Gaussian mixtures
16+
- Learning embeddings of data on product manifolds, using features and/or distances
17+
- Training machine learning models on manifold-valued embeddings, including decision trees, random forests, SVMs,
18+
perceptrons, and neural networks.
19+
- Clustering manifold-valued data using Riemannian fuzzy K-Means
1520

1621
📖 **Documentation**: [manify.readthedocs.io](https://manify.readthedocs.io)
17-
18-
## Key Features
19-
- Create and manipulate manifolds with different curvatures (hyperbolic, Euclidean, spherical)
20-
- Build product manifolds by combining multiple spaces with different geometric properties
21-
- Learn embeddings of data in these manifolds
22-
- Train machine learning models that respect the geometry of the embedding space
23-
- Generate synthetic data with known geometric properties for benchmarking
22+
📝 **Manuscript**: [Manify: A Python Library for Learning Non-Euclidean Representations](https://arxiv.org/abs/2503.09576)
23+
🐛 **Issue Tracker**: [Github](https://github.com/pchlenski/manify/issues)
2424

2525
## Installation
2626

@@ -107,6 +107,10 @@ generate the datasets found in `manify.utils.dataloaders`.
107107
notebooks and datasets that were used to develop the library and carry out various benchmarks for the Mixed Curvature
108108
Decision Trees and Random Forests paper.
109109

110+
## Contributing
111+
Please read our [contributing guide](https://github.com/pchlenski/manify/blob/main/CONTRIBUTING.md) for details on how
112+
to contribute to the project.
113+
110114
## Citation
111115
If you use our work, please cite the `Manify` paper:
112116
```bibtex

tests/test_clustering.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import torch
2+
13
from manify.clustering import RiemannianFuzzyKMeans
24
from manify.manifolds import ProductManifold
35

@@ -7,14 +9,14 @@ def test_riemannian_fuzzy_k_means():
79
X, _ = pm.gaussian_mixture(num_points=100)
810

911
for optimizer in ["adam", "adan"]:
10-
kmeans = RiemannianFuzzyKMeans(manifold=pm, n_clusters=5)
12+
kmeans = RiemannianFuzzyKMeans(manifold=pm, n_clusters=5, random_state=42)
1113
kmeans.fit(X)
1214
preds = kmeans.predict(X)
1315
assert preds.shape == (100,), f"Predictions should have shape (100,) (optimizer: {optimizer})"
1416

1517
# Also test with X as a numpy array
1618
X_np = X.numpy()
17-
kmeans = RiemannianFuzzyKMeans(manifold=pm, n_clusters=5)
19+
kmeans = RiemannianFuzzyKMeans(manifold=pm, n_clusters=5, random_state=42)
1820
kmeans.fit(X_np)
1921
preds_np = kmeans.predict(X_np)
2022
assert torch.tensor(preds_np).shape == (100,), f"Predictions should have shape (100,) (optimizer: {optimizer})"
@@ -28,4 +30,3 @@ def test_riemannian_fuzzy_k_means():
2830
kmeans.fit(X0)
2931
preds = kmeans.predict(X0)
3032
assert preds.shape == (100,), f"Predictions should have shape (100,) (optimizer: {optimizer})"
31-

0 commit comments

Comments
 (0)