pyotc 0.2.2__tar.gz → 0.3.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.
- {pyotc-0.2.2 → pyotc-0.3.0}/.github/workflows/build_and_publish.yml +1 -4
- {pyotc-0.2.2 → pyotc-0.3.0}/CHANGELOG.md +5 -0
- pyotc-0.3.0/PKG-INFO +90 -0
- pyotc-0.3.0/README.md +75 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/noxfile.py +2 -2
- {pyotc-0.2.2 → pyotc-0.3.0}/pyproject.toml +7 -1
- pyotc-0.3.0/src/pyotc/__init__.py +16 -0
- pyotc-0.3.0/src/pyotc/otc.py +53 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/test_entropic.py +2 -2
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/test_exact.py +50 -26
- pyotc-0.2.2/INSTALL.md +0 -41
- pyotc-0.2.2/PKG-INFO +0 -38
- pyotc-0.2.2/README.md +0 -23
- pyotc-0.2.2/src/pyotc/__init__.py +0 -5
- pyotc-0.2.2/src/pyotc/otc.py +0 -5
- {pyotc-0.2.2 → pyotc-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/.github/workflows/README.md +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/.github/workflows/lint_and_test.yml +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/.github/workflows/sphinx.yml +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/.gitignore +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/.python-version +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/AUTHORS.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/CONTRIBUTING.md +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/LICENSE +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/MANIFEST.in +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/RELEASE.md +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/INSTALL.md +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/Makefile +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/authors.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/conf.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/contributing.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/history.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/index.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/installation.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/joss/README.md +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/joss/paper.bib +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/joss/paper.md +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/make.bat +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/modules.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.examples.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.graph.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.optimal_transport.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.policy_iteration.dense.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.policy_iteration.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.policy_iteration.sparse.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/readme.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/docs/usage.rst +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/EntropicOTC.ipynb +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/MarkovProcesses.ipynb +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/NetworkExamples.ipynb +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/README.md +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/Sparse.ipynb +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/pyotc_demo.ipynb +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/pytest.ini +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/examples/__init__.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/examples/edge_awareness.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/examples/lollipops.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/examples/stochastic_block_model.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/examples/wheel.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/__init__.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/graph/__init__.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/graph/utils.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/optimal_transport/__init__.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/optimal_transport/logsinkhorn.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/optimal_transport/native.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/optimal_transport/native_refactor.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/optimal_transport/pot.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/__init__.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/__init__.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/approx_tce.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/entropic.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/entropic_tci.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/exact.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/exact_tce.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/exact_tci_lp.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/exact_tci_pot.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/sparse/__init__.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/sparse/exact.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/sparse/exact_tce.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/sparse/exact_tci.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/utils.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/__init__.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/__init__.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/graph data/graph_G1.json +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/graph data/graph_G2.json +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/graph data/molecule_visualization.png +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/examples/__init__.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/examples/test_lollipops.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/examples/test_stochastic_block_model.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/tests/examples/test_wheel.py +0 -0
- {pyotc-0.2.2 → pyotc-0.3.0}/uv.lock +0 -0
|
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.3.0] - 2026-02-03
|
|
11
|
+
* Implement public api
|
|
12
|
+
* Fix and improve codecov test coverage
|
|
13
|
+
* Update instructions for install
|
|
14
|
+
|
|
10
15
|
## [0.2.2] - 2025-10-10
|
|
11
16
|
* Add github actions build wheels and upload them to pypi.
|
|
12
17
|
|
pyotc-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyotc
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Perform optimal transition coupling (OTC) in python.
|
|
5
|
+
Author: Jay Hineman, Yuning Pan, Bongsoo Yi
|
|
6
|
+
License: MIT license
|
|
7
|
+
License-File: AUTHORS.rst
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Requires-Dist: matplotlib>=3.10.0
|
|
11
|
+
Requires-Dist: networkx>=3.4.2
|
|
12
|
+
Requires-Dist: numpy>=2.2.1
|
|
13
|
+
Requires-Dist: pot>=0.9.5
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# pyotc
|
|
17
|
+
[](https://codecov.io/github/pyotc/pyotc)
|
|
18
|
+
|
|
19
|
+
A python implementations of optimal transport coupling algorithms.
|
|
20
|
+
|
|
21
|
+
## Documentation
|
|
22
|
+
Find sphinx documentation [here](https://pyotc.github.io/pyotc/).
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
We expect `pyotc` to be pip-installable across all platforms.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### 1. Install from pypi (Recommended)
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install pyotc
|
|
33
|
+
```
|
|
34
|
+
- Note: `pyotc` requires Python 3.10 or above.
|
|
35
|
+
|
|
36
|
+
### 2. Install from github
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install https://github.com/pyotc/pyotc.git
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 3. Install for Development
|
|
43
|
+
We test in venvs provided by [uv](https://docs.astral.sh/uv/) via [nox](https://nox.thea.codes/en/stable/usage.html#changing-the-sessions-default-backend). It's helpful, but not strictly necessary to do the same.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone https://github.com/pyotc/pyotc.git
|
|
47
|
+
cd pyotc
|
|
48
|
+
pip install -e .
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### `uv` workflow
|
|
52
|
+
Install the [uv tool](https://docs.astral.sh/uv/getting-started/installation/). Then
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
git clone https://github.com/pyotc/pyotc.git
|
|
56
|
+
cd pyotc
|
|
57
|
+
uv sync
|
|
58
|
+
uv pip install -e .
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
To verify your installation, run
|
|
62
|
+
```bash
|
|
63
|
+
uv run pytest
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Run Tests
|
|
67
|
+
With a `uv` setup one can simply
|
|
68
|
+
```bash
|
|
69
|
+
uv run pytest
|
|
70
|
+
```
|
|
71
|
+
Otherwise, in `pip` installed context with deps met, `pytest` should behave as expected.
|
|
72
|
+
|
|
73
|
+
## Contributing
|
|
74
|
+
Guidelines for contribution to `pyotc` are provided in [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
75
|
+
|
|
76
|
+
## Changelog
|
|
77
|
+
A summary of changes and guide to versioning are recoreded in [CHANGELOG.md](./CHANGELOG.md).
|
|
78
|
+
|
|
79
|
+
## Citing this Repository
|
|
80
|
+
If you wish to cite our work, please use the following BibTeX code:
|
|
81
|
+
```bibtex
|
|
82
|
+
@article{yi2025alignment,
|
|
83
|
+
title={Alignment and comparison of directed networks via transition couplings of random walks},
|
|
84
|
+
author={Yi, Bongsoo and O'Connor, Kevin and McGoff, Kevin and Nobel, Andrew B},
|
|
85
|
+
journal={Journal of the Royal Statistical Society Series B: Statistical Methodology},
|
|
86
|
+
pages={qkae085},
|
|
87
|
+
year={2024},
|
|
88
|
+
doi = {10.1093/jrsssb/qkae085}
|
|
89
|
+
}
|
|
90
|
+
```
|
pyotc-0.3.0/README.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# pyotc
|
|
2
|
+
[](https://codecov.io/github/pyotc/pyotc)
|
|
3
|
+
|
|
4
|
+
A python implementations of optimal transport coupling algorithms.
|
|
5
|
+
|
|
6
|
+
## Documentation
|
|
7
|
+
Find sphinx documentation [here](https://pyotc.github.io/pyotc/).
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
We expect `pyotc` to be pip-installable across all platforms.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### 1. Install from pypi (Recommended)
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install pyotc
|
|
18
|
+
```
|
|
19
|
+
- Note: `pyotc` requires Python 3.10 or above.
|
|
20
|
+
|
|
21
|
+
### 2. Install from github
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install https://github.com/pyotc/pyotc.git
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 3. Install for Development
|
|
28
|
+
We test in venvs provided by [uv](https://docs.astral.sh/uv/) via [nox](https://nox.thea.codes/en/stable/usage.html#changing-the-sessions-default-backend). It's helpful, but not strictly necessary to do the same.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git clone https://github.com/pyotc/pyotc.git
|
|
32
|
+
cd pyotc
|
|
33
|
+
pip install -e .
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### `uv` workflow
|
|
37
|
+
Install the [uv tool](https://docs.astral.sh/uv/getting-started/installation/). Then
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
git clone https://github.com/pyotc/pyotc.git
|
|
41
|
+
cd pyotc
|
|
42
|
+
uv sync
|
|
43
|
+
uv pip install -e .
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
To verify your installation, run
|
|
47
|
+
```bash
|
|
48
|
+
uv run pytest
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Run Tests
|
|
52
|
+
With a `uv` setup one can simply
|
|
53
|
+
```bash
|
|
54
|
+
uv run pytest
|
|
55
|
+
```
|
|
56
|
+
Otherwise, in `pip` installed context with deps met, `pytest` should behave as expected.
|
|
57
|
+
|
|
58
|
+
## Contributing
|
|
59
|
+
Guidelines for contribution to `pyotc` are provided in [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
60
|
+
|
|
61
|
+
## Changelog
|
|
62
|
+
A summary of changes and guide to versioning are recoreded in [CHANGELOG.md](./CHANGELOG.md).
|
|
63
|
+
|
|
64
|
+
## Citing this Repository
|
|
65
|
+
If you wish to cite our work, please use the following BibTeX code:
|
|
66
|
+
```bibtex
|
|
67
|
+
@article{yi2025alignment,
|
|
68
|
+
title={Alignment and comparison of directed networks via transition couplings of random walks},
|
|
69
|
+
author={Yi, Bongsoo and O'Connor, Kevin and McGoff, Kevin and Nobel, Andrew B},
|
|
70
|
+
journal={Journal of the Royal Statistical Society Series B: Statistical Methodology},
|
|
71
|
+
pages={qkae085},
|
|
72
|
+
year={2024},
|
|
73
|
+
doi = {10.1093/jrsssb/qkae085}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
@@ -23,6 +23,6 @@ def format_check(session):
|
|
|
23
23
|
|
|
24
24
|
@session
|
|
25
25
|
def tests(session):
|
|
26
|
-
session.install(".")
|
|
26
|
+
session.install("-e", ".")
|
|
27
27
|
session.install("pytest", "pytest-cov")
|
|
28
|
-
session.run("pytest")
|
|
28
|
+
session.run("pytest", "--cov=pyotc", "--cov-report=term", "--cov-report=xml")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pyotc"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
authors = [
|
|
5
5
|
{name="Jay Hineman"},
|
|
6
6
|
{name="Yuning Pan"},
|
|
@@ -45,3 +45,9 @@ name = "testpypi"
|
|
|
45
45
|
url = "https://test.pypi.org/simple/"
|
|
46
46
|
publish-url = "https://test.pypi.org/legacy/"
|
|
47
47
|
explicit = true
|
|
48
|
+
|
|
49
|
+
[tool.coverage.run]
|
|
50
|
+
omit = [
|
|
51
|
+
"src/pyotc/otc_backend/optimal_transport/native_refactor.py",
|
|
52
|
+
"src/pyotc/otc_backend/graph/utils.py",
|
|
53
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Top-level package for pyotc."""
|
|
2
|
+
|
|
3
|
+
__author__ = """Jay Hineman"""
|
|
4
|
+
__email__ = "jay.hineman@gmail.com"
|
|
5
|
+
__version__ = "0.3.0"
|
|
6
|
+
|
|
7
|
+
# Public API re-exports
|
|
8
|
+
from .otc import entropic_otc, exact_otc
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"exact_otc",
|
|
12
|
+
"entropic_otc",
|
|
13
|
+
"__author__",
|
|
14
|
+
"__email__",
|
|
15
|
+
"__version__",
|
|
16
|
+
]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Main entry point for otc funcitonality"""
|
|
2
|
+
|
|
3
|
+
from .otc_backend.policy_iteration.dense.exact import exact_otc as _exact_otc_dense
|
|
4
|
+
from .otc_backend.policy_iteration.sparse.exact import exact_otc as _exact_otc_sparse
|
|
5
|
+
from .otc_backend.policy_iteration.dense.entropic import entropic_otc as _entropic_otc
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def exact_otc(
|
|
9
|
+
P1,
|
|
10
|
+
P2,
|
|
11
|
+
c,
|
|
12
|
+
*,
|
|
13
|
+
stat_dist="best",
|
|
14
|
+
backend="dense",
|
|
15
|
+
max_iter=None,
|
|
16
|
+
):
|
|
17
|
+
if backend == "dense":
|
|
18
|
+
return _exact_otc_dense(P1, P2, c, stat_dist=stat_dist)
|
|
19
|
+
elif backend == "sparse":
|
|
20
|
+
if max_iter is None:
|
|
21
|
+
return _exact_otc_sparse(P1, P2, c, stat_dist=stat_dist)
|
|
22
|
+
return _exact_otc_sparse(P1, P2, c, stat_dist=stat_dist, max_iter=max_iter)
|
|
23
|
+
else:
|
|
24
|
+
raise ValueError("Unknown backend: {backend}. Choose from {'dense', 'sparse'}.")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def entropic_otc(
|
|
28
|
+
Px,
|
|
29
|
+
Py,
|
|
30
|
+
c,
|
|
31
|
+
*,
|
|
32
|
+
L=100,
|
|
33
|
+
T=100,
|
|
34
|
+
xi=0.1,
|
|
35
|
+
method="logsinkhorn",
|
|
36
|
+
sink_iter=100,
|
|
37
|
+
reg_num=None,
|
|
38
|
+
get_sd=False,
|
|
39
|
+
silent=True,
|
|
40
|
+
):
|
|
41
|
+
return _entropic_otc(
|
|
42
|
+
Px,
|
|
43
|
+
Py,
|
|
44
|
+
c,
|
|
45
|
+
L=L,
|
|
46
|
+
T=T,
|
|
47
|
+
xi=xi,
|
|
48
|
+
method=method,
|
|
49
|
+
sink_iter=sink_iter,
|
|
50
|
+
reg_num=reg_num,
|
|
51
|
+
get_sd=get_sd,
|
|
52
|
+
silent=silent,
|
|
53
|
+
)
|
|
@@ -5,7 +5,7 @@ import networkx as nx
|
|
|
5
5
|
import time
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
|
-
from pyotc
|
|
8
|
+
from pyotc import entropic_otc
|
|
9
9
|
from pyotc.otc_backend.graph.utils import adj_to_trans, get_degree_cost
|
|
10
10
|
from pyotc.examples.stochastic_block_model import stochastic_block_model
|
|
11
11
|
from pyotc.examples.wheel import wheel_1, wheel_2, wheel_3
|
|
@@ -67,7 +67,7 @@ def test_wheel_exact_otc():
|
|
|
67
67
|
# entropic otc
|
|
68
68
|
start = time.time()
|
|
69
69
|
exp_cost12, _, _ = entropic_otc(
|
|
70
|
-
P1, P2, c12, get_sd=True, L=25, T=50, xi=0.1, sink_iter=10
|
|
70
|
+
P1, P2, c12, get_sd=True, L=25, T=50, xi=0.1, sink_iter=10, silent=False
|
|
71
71
|
)
|
|
72
72
|
exp_cost13, _, _ = entropic_otc(
|
|
73
73
|
P1, P3, c13, get_sd=True, L=25, T=50, xi=0.1, sink_iter=10
|
|
@@ -5,11 +5,8 @@ import networkx as nx
|
|
|
5
5
|
import time
|
|
6
6
|
import pytest
|
|
7
7
|
|
|
8
|
+
from pyotc import exact_otc
|
|
8
9
|
from pyotc.otc_backend.policy_iteration.dense.exact import exact_otc_lp
|
|
9
|
-
from pyotc.otc_backend.policy_iteration.dense.exact import exact_otc as exact_otc_dense
|
|
10
|
-
from pyotc.otc_backend.policy_iteration.sparse.exact import (
|
|
11
|
-
exact_otc as exact_otc_sparse,
|
|
12
|
-
)
|
|
13
10
|
from pyotc.otc_backend.graph.utils import adj_to_trans, get_degree_cost
|
|
14
11
|
from pyotc.examples.stochastic_block_model import stochastic_block_model
|
|
15
12
|
from pyotc.examples.wheel import wheel_1, wheel_2, wheel_3
|
|
@@ -41,27 +38,22 @@ test_data = zip(trans, costs)
|
|
|
41
38
|
|
|
42
39
|
@pytest.mark.parametrize("transition, cost", test_data)
|
|
43
40
|
def test_sbm_exact_otc(transition, cost):
|
|
44
|
-
# scipy linprog algo
|
|
45
|
-
start = time.time()
|
|
46
|
-
exp_cost1, _, _ = exact_otc_lp(transition["P1"], transition["P2"], cost)
|
|
47
|
-
end = time.time()
|
|
48
|
-
print(f"`exact_otc` (scipy) run time: {end - start}")
|
|
49
|
-
|
|
50
41
|
# python optimal transport algo (numpy)
|
|
51
42
|
start = time.time()
|
|
52
|
-
|
|
43
|
+
exp_cost1, _, _ = exact_otc(transition["P1"], transition["P2"], cost)
|
|
53
44
|
end = time.time()
|
|
54
45
|
print(f"`exact_otc` (pot) run time: {end - start}")
|
|
55
46
|
|
|
56
47
|
# python optimal transport algo (scipy.sparse)
|
|
57
48
|
start = time.time()
|
|
58
|
-
|
|
49
|
+
exp_cost2, _, _ = exact_otc(
|
|
50
|
+
transition["P1"], transition["P2"], cost, backend="sparse", max_iter=100
|
|
51
|
+
)
|
|
59
52
|
end = time.time()
|
|
60
53
|
print(f"`exact_otc` (pot) run time: {end - start}")
|
|
61
54
|
|
|
62
55
|
# check consistency
|
|
63
56
|
assert np.allclose(exp_cost1, exp_cost2)
|
|
64
|
-
assert np.allclose(exp_cost1, exp_cost3)
|
|
65
57
|
|
|
66
58
|
|
|
67
59
|
# 2. Test exact OTC on wheel graph
|
|
@@ -78,17 +70,24 @@ wheel_c = [
|
|
|
78
70
|
|
|
79
71
|
|
|
80
72
|
def test_wheel_exact_otc():
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
73
|
+
exp_cost12_dense, _, _ = exact_otc(
|
|
74
|
+
wheel_P[0], wheel_P[1], wheel_c[0], stat_dist=None, backend="dense"
|
|
75
|
+
)
|
|
76
|
+
exp_cost12_sparse, _, _ = exact_otc(
|
|
77
|
+
wheel_P[0], wheel_P[1], wheel_c[0], stat_dist=None, backend="sparse"
|
|
78
|
+
)
|
|
84
79
|
|
|
85
|
-
exp_cost13_dense, _, _ =
|
|
86
|
-
|
|
80
|
+
exp_cost13_dense, _, _ = exact_otc(
|
|
81
|
+
wheel_P[0], wheel_P[2], wheel_c[1], stat_dist=None, backend="dense"
|
|
82
|
+
)
|
|
83
|
+
exp_cost13_sparse, _, _ = exact_otc(
|
|
84
|
+
wheel_P[0], wheel_P[2], wheel_c[1], stat_dist=None, backend="sparse"
|
|
85
|
+
)
|
|
87
86
|
|
|
88
87
|
# check consistency
|
|
89
88
|
assert np.allclose(exp_cost12_dense, 2.6551724137931036)
|
|
90
89
|
assert np.allclose(exp_cost12_dense, exp_cost12_sparse)
|
|
91
|
-
assert np.allclose(exp_cost13_dense, 2.
|
|
90
|
+
assert np.allclose(exp_cost13_dense, 2.5517241379310316)
|
|
92
91
|
assert np.allclose(exp_cost13_dense, exp_cost13_sparse)
|
|
93
92
|
|
|
94
93
|
|
|
@@ -103,14 +102,39 @@ edge_awareness_c = [c21, c23]
|
|
|
103
102
|
|
|
104
103
|
|
|
105
104
|
def test_edge_awareness_exact_otc():
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
edge_awareness_P[
|
|
105
|
+
exp_cost21, _, _ = exact_otc(
|
|
106
|
+
edge_awareness_P[1],
|
|
107
|
+
edge_awareness_P[0],
|
|
108
|
+
edge_awareness_c[0],
|
|
109
|
+
stat_dist="eigen",
|
|
110
|
+
backend="dense",
|
|
111
|
+
)
|
|
112
|
+
exp_cost21_lp, _, _ = exact_otc_lp(
|
|
113
|
+
edge_awareness_P[1], edge_awareness_P[0], edge_awareness_c[0], stat_dist="best"
|
|
114
|
+
)
|
|
115
|
+
exp_cost23, _, _ = exact_otc(
|
|
116
|
+
edge_awareness_P[1],
|
|
117
|
+
edge_awareness_P[2],
|
|
118
|
+
edge_awareness_c[1],
|
|
119
|
+
stat_dist="iterative",
|
|
120
|
+
backend="dense",
|
|
109
121
|
)
|
|
110
|
-
|
|
111
|
-
edge_awareness_P[1], edge_awareness_P[2], edge_awareness_c[1]
|
|
122
|
+
exp_cost23_lp, _, _ = exact_otc_lp(
|
|
123
|
+
edge_awareness_P[1], edge_awareness_P[2], edge_awareness_c[1], stat_dist=None
|
|
112
124
|
)
|
|
113
125
|
|
|
114
126
|
# check consistency
|
|
115
|
-
assert np.allclose(exp_cost21, 0.
|
|
116
|
-
assert np.allclose(
|
|
127
|
+
assert np.allclose(exp_cost21, 0.5714285714285724)
|
|
128
|
+
assert np.allclose(exp_cost21, exp_cost21_lp)
|
|
129
|
+
assert np.allclose(exp_cost23, 0.4464098659648501)
|
|
130
|
+
assert np.allclose(exp_cost23, exp_cost23_lp)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def test_exact_otc_invalid_backend():
|
|
134
|
+
with pytest.raises(ValueError):
|
|
135
|
+
exact_otc(
|
|
136
|
+
edge_awareness_P[1],
|
|
137
|
+
edge_awareness_P[2],
|
|
138
|
+
edge_awareness_c[1],
|
|
139
|
+
backend="invalid_backend",
|
|
140
|
+
)
|
pyotc-0.2.2/INSTALL.md
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# Install
|
|
2
|
-
We expect pyotc to be pip-installable across all platforms.
|
|
3
|
-
|
|
4
|
-
## Install for usage
|
|
5
|
-
### From pypi
|
|
6
|
-
|
|
7
|
-
```pip install pyotc```
|
|
8
|
-
[TODO#26](https://github.com/pyotc/pyotc/issues/26)
|
|
9
|
-
|
|
10
|
-
### From github
|
|
11
|
-
|
|
12
|
-
```pip install https://github.com/pyotc/pyotc.git```
|
|
13
|
-
|
|
14
|
-
## Install for development
|
|
15
|
-
We test in venvs provided by [uv](https://docs.astral.sh/uv/) via [nox](https://nox.thea.codes/en/stable/usage.html#changing-the-sessions-default-backend). It's helpful, but not strictly necessary to do the same.
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
git clone https://github.com/pyotc/pyotc.git
|
|
19
|
-
cd pyotc
|
|
20
|
-
pip install -e .
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### `uv` workflow
|
|
24
|
-
[Install the uv tool](https://docs.astral.sh/uv/getting-started/installation/).
|
|
25
|
-
|
|
26
|
-
Then
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
git clone https://github.com/pyotc/pyotc.git
|
|
30
|
-
cd pyotc
|
|
31
|
-
uv sync
|
|
32
|
-
uv pip install -e .
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
To verify your installation, run
|
|
36
|
-
```bash
|
|
37
|
-
uv run pytest
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
pyotc-0.2.2/PKG-INFO
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: pyotc
|
|
3
|
-
Version: 0.2.2
|
|
4
|
-
Summary: Perform optimal transition coupling (OTC) in python.
|
|
5
|
-
Author: Jay Hineman, Yuning Pan, Bongsoo Yi
|
|
6
|
-
License: MIT license
|
|
7
|
-
License-File: AUTHORS.rst
|
|
8
|
-
License-File: LICENSE
|
|
9
|
-
Requires-Python: >=3.10
|
|
10
|
-
Requires-Dist: matplotlib>=3.10.0
|
|
11
|
-
Requires-Dist: networkx>=3.4.2
|
|
12
|
-
Requires-Dist: numpy>=2.2.1
|
|
13
|
-
Requires-Dist: pot>=0.9.5
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
|
|
16
|
-
# pyotc
|
|
17
|
-
[](https://codecov.io/github/pyotc/pyotc)
|
|
18
|
-
|
|
19
|
-
A python implementations of optimal transport coupling algorithms.
|
|
20
|
-
|
|
21
|
-
## Documentation
|
|
22
|
-
Find sphinx documentation [here](https://pyotc.github.io/pyotc/).
|
|
23
|
-
|
|
24
|
-
## Install
|
|
25
|
-
See [install instructions](INSTALL.md)
|
|
26
|
-
|
|
27
|
-
## Run Tests
|
|
28
|
-
With a `uv` setup one can simply
|
|
29
|
-
```bash
|
|
30
|
-
uv run pytest
|
|
31
|
-
```
|
|
32
|
-
Otherwise, in `pip` installed context with deps met, `pytest` should behave as expected.
|
|
33
|
-
|
|
34
|
-
## Contributing
|
|
35
|
-
Guidelines for contribution to `pyotc` are provided in [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
36
|
-
|
|
37
|
-
## Changelog
|
|
38
|
-
A summary of changes and guide to versioning are recoreded in [CHANGELOG.md](./CHANGELOG.md).
|
pyotc-0.2.2/README.md
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# pyotc
|
|
2
|
-
[](https://codecov.io/github/pyotc/pyotc)
|
|
3
|
-
|
|
4
|
-
A python implementations of optimal transport coupling algorithms.
|
|
5
|
-
|
|
6
|
-
## Documentation
|
|
7
|
-
Find sphinx documentation [here](https://pyotc.github.io/pyotc/).
|
|
8
|
-
|
|
9
|
-
## Install
|
|
10
|
-
See [install instructions](INSTALL.md)
|
|
11
|
-
|
|
12
|
-
## Run Tests
|
|
13
|
-
With a `uv` setup one can simply
|
|
14
|
-
```bash
|
|
15
|
-
uv run pytest
|
|
16
|
-
```
|
|
17
|
-
Otherwise, in `pip` installed context with deps met, `pytest` should behave as expected.
|
|
18
|
-
|
|
19
|
-
## Contributing
|
|
20
|
-
Guidelines for contribution to `pyotc` are provided in [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
21
|
-
|
|
22
|
-
## Changelog
|
|
23
|
-
A summary of changes and guide to versioning are recoreded in [CHANGELOG.md](./CHANGELOG.md).
|
pyotc-0.2.2/src/pyotc/otc.py
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|