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.
Files changed (95) hide show
  1. {pyotc-0.2.2 → pyotc-0.3.0}/.github/workflows/build_and_publish.yml +1 -4
  2. {pyotc-0.2.2 → pyotc-0.3.0}/CHANGELOG.md +5 -0
  3. pyotc-0.3.0/PKG-INFO +90 -0
  4. pyotc-0.3.0/README.md +75 -0
  5. {pyotc-0.2.2 → pyotc-0.3.0}/noxfile.py +2 -2
  6. {pyotc-0.2.2 → pyotc-0.3.0}/pyproject.toml +7 -1
  7. pyotc-0.3.0/src/pyotc/__init__.py +16 -0
  8. pyotc-0.3.0/src/pyotc/otc.py +53 -0
  9. {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/test_entropic.py +2 -2
  10. {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/test_exact.py +50 -26
  11. pyotc-0.2.2/INSTALL.md +0 -41
  12. pyotc-0.2.2/PKG-INFO +0 -38
  13. pyotc-0.2.2/README.md +0 -23
  14. pyotc-0.2.2/src/pyotc/__init__.py +0 -5
  15. pyotc-0.2.2/src/pyotc/otc.py +0 -5
  16. {pyotc-0.2.2 → pyotc-0.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  17. {pyotc-0.2.2 → pyotc-0.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  18. {pyotc-0.2.2 → pyotc-0.3.0}/.github/workflows/README.md +0 -0
  19. {pyotc-0.2.2 → pyotc-0.3.0}/.github/workflows/lint_and_test.yml +0 -0
  20. {pyotc-0.2.2 → pyotc-0.3.0}/.github/workflows/sphinx.yml +0 -0
  21. {pyotc-0.2.2 → pyotc-0.3.0}/.gitignore +0 -0
  22. {pyotc-0.2.2 → pyotc-0.3.0}/.python-version +0 -0
  23. {pyotc-0.2.2 → pyotc-0.3.0}/AUTHORS.rst +0 -0
  24. {pyotc-0.2.2 → pyotc-0.3.0}/CONTRIBUTING.md +0 -0
  25. {pyotc-0.2.2 → pyotc-0.3.0}/LICENSE +0 -0
  26. {pyotc-0.2.2 → pyotc-0.3.0}/MANIFEST.in +0 -0
  27. {pyotc-0.2.2 → pyotc-0.3.0}/RELEASE.md +0 -0
  28. {pyotc-0.2.2 → pyotc-0.3.0}/docs/INSTALL.md +0 -0
  29. {pyotc-0.2.2 → pyotc-0.3.0}/docs/Makefile +0 -0
  30. {pyotc-0.2.2 → pyotc-0.3.0}/docs/authors.rst +0 -0
  31. {pyotc-0.2.2 → pyotc-0.3.0}/docs/conf.py +0 -0
  32. {pyotc-0.2.2 → pyotc-0.3.0}/docs/contributing.rst +0 -0
  33. {pyotc-0.2.2 → pyotc-0.3.0}/docs/history.rst +0 -0
  34. {pyotc-0.2.2 → pyotc-0.3.0}/docs/index.rst +0 -0
  35. {pyotc-0.2.2 → pyotc-0.3.0}/docs/installation.rst +0 -0
  36. {pyotc-0.2.2 → pyotc-0.3.0}/docs/joss/README.md +0 -0
  37. {pyotc-0.2.2 → pyotc-0.3.0}/docs/joss/paper.bib +0 -0
  38. {pyotc-0.2.2 → pyotc-0.3.0}/docs/joss/paper.md +0 -0
  39. {pyotc-0.2.2 → pyotc-0.3.0}/docs/make.bat +0 -0
  40. {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/modules.rst +0 -0
  41. {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.examples.rst +0 -0
  42. {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.graph.rst +0 -0
  43. {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.optimal_transport.rst +0 -0
  44. {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.policy_iteration.dense.rst +0 -0
  45. {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.policy_iteration.rst +0 -0
  46. {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.policy_iteration.sparse.rst +0 -0
  47. {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.otc_backend.rst +0 -0
  48. {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules/pyotc.rst +0 -0
  49. {pyotc-0.2.2 → pyotc-0.3.0}/docs/modules.rst +0 -0
  50. {pyotc-0.2.2 → pyotc-0.3.0}/docs/readme.rst +0 -0
  51. {pyotc-0.2.2 → pyotc-0.3.0}/docs/usage.rst +0 -0
  52. {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/EntropicOTC.ipynb +0 -0
  53. {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/MarkovProcesses.ipynb +0 -0
  54. {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/NetworkExamples.ipynb +0 -0
  55. {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/README.md +0 -0
  56. {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/Sparse.ipynb +0 -0
  57. {pyotc-0.2.2 → pyotc-0.3.0}/notebooks/pyotc_demo.ipynb +0 -0
  58. {pyotc-0.2.2 → pyotc-0.3.0}/pytest.ini +0 -0
  59. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/examples/__init__.py +0 -0
  60. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/examples/edge_awareness.py +0 -0
  61. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/examples/lollipops.py +0 -0
  62. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/examples/stochastic_block_model.py +0 -0
  63. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/examples/wheel.py +0 -0
  64. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/__init__.py +0 -0
  65. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/graph/__init__.py +0 -0
  66. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/graph/utils.py +0 -0
  67. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/optimal_transport/__init__.py +0 -0
  68. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/optimal_transport/logsinkhorn.py +0 -0
  69. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/optimal_transport/native.py +0 -0
  70. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/optimal_transport/native_refactor.py +0 -0
  71. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/optimal_transport/pot.py +0 -0
  72. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/__init__.py +0 -0
  73. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/__init__.py +0 -0
  74. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/approx_tce.py +0 -0
  75. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/entropic.py +0 -0
  76. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/entropic_tci.py +0 -0
  77. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/exact.py +0 -0
  78. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/exact_tce.py +0 -0
  79. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/exact_tci_lp.py +0 -0
  80. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/dense/exact_tci_pot.py +0 -0
  81. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/sparse/__init__.py +0 -0
  82. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/sparse/exact.py +0 -0
  83. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/sparse/exact_tce.py +0 -0
  84. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/sparse/exact_tci.py +0 -0
  85. {pyotc-0.2.2 → pyotc-0.3.0}/src/pyotc/otc_backend/policy_iteration/utils.py +0 -0
  86. {pyotc-0.2.2 → pyotc-0.3.0}/tests/__init__.py +0 -0
  87. {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/__init__.py +0 -0
  88. {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/graph data/graph_G1.json +0 -0
  89. {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/graph data/graph_G2.json +0 -0
  90. {pyotc-0.2.2 → pyotc-0.3.0}/tests/benchmark/graph data/molecule_visualization.png +0 -0
  91. {pyotc-0.2.2 → pyotc-0.3.0}/tests/examples/__init__.py +0 -0
  92. {pyotc-0.2.2 → pyotc-0.3.0}/tests/examples/test_lollipops.py +0 -0
  93. {pyotc-0.2.2 → pyotc-0.3.0}/tests/examples/test_stochastic_block_model.py +0 -0
  94. {pyotc-0.2.2 → pyotc-0.3.0}/tests/examples/test_wheel.py +0 -0
  95. {pyotc-0.2.2 → pyotc-0.3.0}/uv.lock +0 -0
@@ -10,11 +10,8 @@ name: build and publish
10
10
 
11
11
  on:
12
12
  release:
13
- types: [published]
13
+ types: [published, prereleased]
14
14
  workflow_dispatch:
15
- push:
16
- branches:
17
- - '77-fix-pypi-upload'
18
15
 
19
16
  permissions:
20
17
  contents: read
@@ -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
+ [![codecov](https://codecov.io/github/pyotc/pyotc/graph/badge.svg?token=52QPNW0AP7)](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
+ [![codecov](https://codecov.io/github/pyotc/pyotc/graph/badge.svg?token=52QPNW0AP7)](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.2.2"
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.otc_backend.policy_iteration.dense.entropic import entropic_otc
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
- exp_cost2, _, _ = exact_otc_dense(transition["P1"], transition["P2"], cost)
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
- exp_cost3, _, _ = exact_otc_sparse(transition["P1"], transition["P2"], cost)
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
- # python optimal transport algo
82
- exp_cost12_dense, _, _ = exact_otc_dense(wheel_P[0], wheel_P[1], wheel_c[0])
83
- exp_cost12_sparse, _, _ = exact_otc_sparse(wheel_P[0], wheel_P[1], wheel_c[0])
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, _, _ = exact_otc_dense(wheel_P[0], wheel_P[2], wheel_c[1])
86
- exp_cost13_sparse, _, _ = exact_otc_sparse(wheel_P[0], wheel_P[2], wheel_c[1])
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.551724137931033)
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
- # python optimal transport algo
107
- exp_cost21, _, _ = exact_otc_dense(
108
- edge_awareness_P[1], edge_awareness_P[0], edge_awareness_c[0]
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
- exp_cost23, _, _ = exact_otc_dense(
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.5714285714285714)
116
- assert np.allclose(exp_cost23, 0.4464098659648351)
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
- [![codecov](https://codecov.io/github/pyotc/pyotc/graph/badge.svg?token=52QPNW0AP7)](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
- [![codecov](https://codecov.io/github/pyotc/pyotc/graph/badge.svg?token=52QPNW0AP7)](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).
@@ -1,5 +0,0 @@
1
- """Top-level package for pyotc."""
2
-
3
- __author__ = """Jay Hineman"""
4
- __email__ = "jay.hineman@gmail.com"
5
- __version__ = "0.1.0"
@@ -1,5 +0,0 @@
1
- """Main entry point for otc funcitonality"""
2
-
3
-
4
- def exact_OTC():
5
- raise NotImplementedError
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