tinto 0.1.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.
- tinto-0.1.0/.github/README.md +115 -0
- tinto-0.1.0/.gitignore +137 -0
- tinto-0.1.0/AUTHORS.md +9 -0
- tinto-0.1.0/CONTRIBUTING.md +101 -0
- tinto-0.1.0/HISTORY.md +100 -0
- tinto-0.1.0/PKG-INFO +130 -0
- tinto-0.1.0/citation.cff +17 -0
- tinto-0.1.0/conftest.py +20 -0
- tinto-0.1.0/docs/_static/logo.svg +20 -0
- tinto-0.1.0/docs/companion/exact_stabilization_time.ipynb +1678 -0
- tinto-0.1.0/docs/companion/index.md +17 -0
- tinto-0.1.0/docs/conf.py +215 -0
- tinto-0.1.0/docs/index.md +18 -0
- tinto-0.1.0/docs/presentation/authors.md +2 -0
- tinto-0.1.0/docs/presentation/contributing.md +2 -0
- tinto-0.1.0/docs/presentation/history.md +2 -0
- tinto-0.1.0/docs/presentation/index.md +10 -0
- tinto-0.1.0/docs/presentation/installation.md +48 -0
- tinto-0.1.0/docs/presentation/readme.md +5 -0
- tinto-0.1.0/docs/reference/campaigns.md +15 -0
- tinto-0.1.0/docs/reference/configs.md +15 -0
- tinto-0.1.0/docs/reference/dynamics.md +23 -0
- tinto-0.1.0/docs/reference/estimate.md +8 -0
- tinto-0.1.0/docs/reference/exact.md +8 -0
- tinto-0.1.0/docs/reference/experiments.md +9 -0
- tinto-0.1.0/docs/reference/graphs.md +9 -0
- tinto-0.1.0/docs/reference/guards.md +9 -0
- tinto-0.1.0/docs/reference/index.md +13 -0
- tinto-0.1.0/docs/reference/io.md +9 -0
- tinto-0.1.0/docs/reference/oracle.md +8 -0
- tinto-0.1.0/docs/reference/runners.md +9 -0
- tinto-0.1.0/docs/reference/schedulers.md +9 -0
- tinto-0.1.0/docs/reference/solvers.md +9 -0
- tinto-0.1.0/docs/reference/starters.md +18 -0
- tinto-0.1.0/docs/reference/theory/bipartite.md +6 -0
- tinto-0.1.0/docs/reference/theory/cayley.md +6 -0
- tinto-0.1.0/docs/reference/theory/erdos_renyi.md +6 -0
- tinto-0.1.0/docs/reference/theory/general.md +6 -0
- tinto-0.1.0/docs/reference/theory/path_cycle.md +6 -0
- tinto-0.1.0/docs/reference/theory/star.md +6 -0
- tinto-0.1.0/docs/reference/theory.md +16 -0
- tinto-0.1.0/docs/tutorials/basics.ipynb +489 -0
- tinto-0.1.0/docs/tutorials/index.md +6 -0
- tinto-0.1.0/docs/tutorials/introduction.ipynb +2224 -0
- tinto-0.1.0/pyproject.toml +80 -0
- tinto-0.1.0/tests/__init__.py +1 -0
- tinto-0.1.0/tests/test_exact.py +80 -0
- tinto-0.1.0/tests/test_independence.py +57 -0
- tinto-0.1.0/tests/test_oracle.py +189 -0
- tinto-0.1.0/tests/test_theory.py +201 -0
- tinto-0.1.0/tests/test_tinto.py +470 -0
- tinto-0.1.0/tinto/__init__.py +12 -0
- tinto-0.1.0/tinto/configs.py +431 -0
- tinto-0.1.0/tinto/estimate.py +804 -0
- tinto-0.1.0/tinto/exact.py +311 -0
- tinto-0.1.0/tinto/experiments.py +1132 -0
- tinto-0.1.0/tinto/graphs.py +604 -0
- tinto-0.1.0/tinto/guards.py +276 -0
- tinto-0.1.0/tinto/io.py +52 -0
- tinto-0.1.0/tinto/oracle.py +295 -0
- tinto-0.1.0/tinto/runners.py +239 -0
- tinto-0.1.0/tinto/schedulers.py +516 -0
- tinto-0.1.0/tinto/solvers.py +414 -0
- tinto-0.1.0/tinto/starters.py +460 -0
- tinto-0.1.0/tinto/theory/__init__.py +28 -0
- tinto-0.1.0/tinto/theory/_egf.py +111 -0
- tinto-0.1.0/tinto/theory/bipartite.py +182 -0
- tinto-0.1.0/tinto/theory/cayley.py +319 -0
- tinto-0.1.0/tinto/theory/erdos_renyi.py +203 -0
- tinto-0.1.0/tinto/theory/general.py +374 -0
- tinto-0.1.0/tinto/theory/path_cycle.py +282 -0
- tinto-0.1.0/tinto/theory/star.py +88 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# <img src="../docs/_static/logo.svg" alt="Tinto logo" width="48" valign="middle" /> Tinto
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
[](https://pypi.python.org/pypi/tinto)
|
|
5
|
+
[](https://github.com/balouf/tinto/actions?query=workflow%3Abuild)
|
|
6
|
+
[](https://github.com/balouf/tinto/actions?query=workflow%3Adocs)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](https://codecov.io/gh/balouf/tinto/tree/main)
|
|
9
|
+
|
|
10
|
+
How long does a self-stabilizing graph coloring take to settle? Tinto measures it with a Numba-compiled Monte Carlo over pluggable graphs, guards, schedulers and recoloring rules, down to the variance and skewness of the stabilization time. For the conflict-guard rule under the random central daemon, it also provides exact results.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
- Free software: MIT
|
|
14
|
+
- Documentation: <https://balouf.github.io/tinto/>.
|
|
15
|
+
- Github: <https://github.com/balouf/tinto>
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- Numba-compiled dynamics: CSR graphs (line, ring, uniform labeled tree,
|
|
21
|
+
Erdős-Rényi `G(n, p)`, bipartite `G(n1, n2, p)`), pluggable guards,
|
|
22
|
+
four schedulers (shuffled, ordered, Bernoulli, independent) and five
|
|
23
|
+
colorers (lowest, next or uniform free color, plus two blind variants
|
|
24
|
+
that may leave clashes behind).
|
|
25
|
+
- Monte-Carlo driver aggregating mean, variance and third central moment
|
|
26
|
+
of both the number of steps and the number of activations before
|
|
27
|
+
stabilization, on a fixed graph or on a fresh random graph per replica.
|
|
28
|
+
- `Experiment` high-level API with cartesian-product sweeps, campaign
|
|
29
|
+
addition, light matplotlib plotting, CSV export, and fits of the
|
|
30
|
+
results (weighted least squares, test for a hidden term, recovery of
|
|
31
|
+
exact fractions).
|
|
32
|
+
- Exact stabilization time of the conflict-guard rule under the random
|
|
33
|
+
central daemon, from three independent sources: the peak oracle, which
|
|
34
|
+
samples it without running the dynamics (`tinto.oracle`), exact
|
|
35
|
+
enumeration on small graphs (`tinto.exact`) and closed forms
|
|
36
|
+
(`tinto.theory`).
|
|
37
|
+
- Companion notebooks that check the numerical statements of the papers.
|
|
38
|
+
- 100% branch-covered by doctest-based examples.
|
|
39
|
+
|
|
40
|
+
## Quickstart
|
|
41
|
+
|
|
42
|
+
Install Tinto:
|
|
43
|
+
|
|
44
|
+
```console
|
|
45
|
+
$ pip install tinto
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Low-level API
|
|
49
|
+
|
|
50
|
+
Drive one trajectory on a line graph:
|
|
51
|
+
|
|
52
|
+
```pycon
|
|
53
|
+
>>> from tinto import graphs, configs, schedulers, solvers, runners
|
|
54
|
+
>>> from tinto.io import set_seed
|
|
55
|
+
>>> set_seed(0)
|
|
56
|
+
>>> Config = configs.make()
|
|
57
|
+
>>> c = Config(graphs.line(20))
|
|
58
|
+
>>> sched = schedulers.shuffled()(c)
|
|
59
|
+
>>> solver = solvers.make()
|
|
60
|
+
>>> steps, activations = runners.simple(c, sched, solver)
|
|
61
|
+
>>> steps > 0
|
|
62
|
+
True
|
|
63
|
+
>>> c.total
|
|
64
|
+
0
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Or Monte-Carlo the moments of both metrics over many replicas:
|
|
68
|
+
|
|
69
|
+
```pycon
|
|
70
|
+
>>> from tinto import starters
|
|
71
|
+
>>> set_seed(0)
|
|
72
|
+
>>> starter = starters.from_graph(Config)(graphs.line(20))
|
|
73
|
+
>>> res = runners.mc(starter, schedulers.shuffled(), solver, n_trials=20)
|
|
74
|
+
>>> mean, var, m3 = res["steps"]
|
|
75
|
+
>>> mean > 0
|
|
76
|
+
True
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### High-level API
|
|
80
|
+
|
|
81
|
+
The `Experiment` class bundles a sweep + the Monte-Carlo runner + plot
|
|
82
|
+
and export helpers. Define an `Iterator` over one parameter, wrap it in
|
|
83
|
+
an `Experiment`, run:
|
|
84
|
+
|
|
85
|
+
```pycon
|
|
86
|
+
>>> from tinto import Experiment, Iterator
|
|
87
|
+
>>> def build_starter(n):
|
|
88
|
+
... return starters.from_graph(Config)(graphs.line(n))
|
|
89
|
+
>>> n_iter = Iterator("starter", [10, 20, 50], name="n", process=build_starter)
|
|
90
|
+
>>> exp = Experiment(
|
|
91
|
+
... "line-sweep",
|
|
92
|
+
... iterator=n_iter,
|
|
93
|
+
... scheduler=schedulers.shuffled(),
|
|
94
|
+
... solver=solver,
|
|
95
|
+
... n_trials=50,
|
|
96
|
+
... )
|
|
97
|
+
>>> _ = exp.run(progress=False)
|
|
98
|
+
>>> exp.results["line-sweep"]["axes"]
|
|
99
|
+
('starter',)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Compose cartesian products with `*` and combine multiple campaigns with
|
|
103
|
+
`+`:
|
|
104
|
+
|
|
105
|
+
```pycon
|
|
106
|
+
>>> kind_iter = Iterator("starter", ["random", "mono"], name="kind")
|
|
107
|
+
>>> # plot or export via exp.plot(x="n", hue="kind") / exp.to_csv(...)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Credits
|
|
111
|
+
|
|
112
|
+
This package was created with [Cookiecutter][CC] and the [Package Helper 3][PH3] project template.
|
|
113
|
+
|
|
114
|
+
[CC]: <https://github.com/audreyr/cookiecutter>
|
|
115
|
+
[PH3]: <https://balouf.github.io/package-helper-3/>
|
tinto-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# build outputs
|
|
2
|
+
*.pdf
|
|
3
|
+
|
|
4
|
+
# python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.pyc
|
|
7
|
+
.ipynb_checkpoints/
|
|
8
|
+
|
|
9
|
+
# editors and OS
|
|
10
|
+
.DS_Store
|
|
11
|
+
Thumbs.db
|
|
12
|
+
|
|
13
|
+
# ---- Python package (from the tinto repository) ----
|
|
14
|
+
# Byte-compiled / optimized / DLL files
|
|
15
|
+
__pycache__/
|
|
16
|
+
*.py[cod]
|
|
17
|
+
*$py.class
|
|
18
|
+
|
|
19
|
+
# C extensions
|
|
20
|
+
*.so
|
|
21
|
+
|
|
22
|
+
# Distribution / packaging
|
|
23
|
+
.Python
|
|
24
|
+
env/
|
|
25
|
+
build/
|
|
26
|
+
develop-eggs/
|
|
27
|
+
dist/
|
|
28
|
+
downloads/
|
|
29
|
+
eggs/
|
|
30
|
+
.eggs/
|
|
31
|
+
lib/
|
|
32
|
+
lib64/
|
|
33
|
+
parts/
|
|
34
|
+
sdist/
|
|
35
|
+
var/
|
|
36
|
+
wheels/
|
|
37
|
+
*.egg-info/
|
|
38
|
+
.installed.cfg
|
|
39
|
+
*.egg
|
|
40
|
+
|
|
41
|
+
# PyInstaller
|
|
42
|
+
# Usually these files are written by a python script from a template
|
|
43
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
44
|
+
*.manifest
|
|
45
|
+
*.spec
|
|
46
|
+
|
|
47
|
+
# Installer logs
|
|
48
|
+
pip-log.txt
|
|
49
|
+
pip-delete-this-directory.txt
|
|
50
|
+
|
|
51
|
+
# Unit test / coverage reports
|
|
52
|
+
htmlcov/
|
|
53
|
+
.tox/
|
|
54
|
+
.coverage
|
|
55
|
+
.coverage.*
|
|
56
|
+
.cache
|
|
57
|
+
nosetests.xml
|
|
58
|
+
coverage.xml
|
|
59
|
+
*.cover
|
|
60
|
+
.hypothesis/
|
|
61
|
+
.pytest_cache/
|
|
62
|
+
|
|
63
|
+
# Translations
|
|
64
|
+
*.mo
|
|
65
|
+
*.pot
|
|
66
|
+
|
|
67
|
+
# Django stuff:
|
|
68
|
+
*.log
|
|
69
|
+
local_settings.py
|
|
70
|
+
|
|
71
|
+
# Flask stuff:
|
|
72
|
+
instance/
|
|
73
|
+
.webassets-cache
|
|
74
|
+
|
|
75
|
+
# Scrapy stuff:
|
|
76
|
+
.scrapy
|
|
77
|
+
|
|
78
|
+
# Sphinx documentation
|
|
79
|
+
docs/_build/
|
|
80
|
+
|
|
81
|
+
# PyBuilder
|
|
82
|
+
target/
|
|
83
|
+
|
|
84
|
+
# Jupyter Notebook
|
|
85
|
+
.ipynb_checkpoints
|
|
86
|
+
|
|
87
|
+
# pyenv
|
|
88
|
+
.python-version
|
|
89
|
+
|
|
90
|
+
# celery beat schedule file
|
|
91
|
+
celerybeat-schedule
|
|
92
|
+
|
|
93
|
+
# SageMath parsed files
|
|
94
|
+
*.sage.py
|
|
95
|
+
|
|
96
|
+
# dotenv
|
|
97
|
+
.env
|
|
98
|
+
|
|
99
|
+
# virtualenv
|
|
100
|
+
.venv
|
|
101
|
+
venv/
|
|
102
|
+
ENV/
|
|
103
|
+
|
|
104
|
+
# Spyder project settings
|
|
105
|
+
.spyderproject
|
|
106
|
+
.spyproject
|
|
107
|
+
|
|
108
|
+
# Rope project settings
|
|
109
|
+
.ropeproject
|
|
110
|
+
|
|
111
|
+
# mkdocs documentation
|
|
112
|
+
/site
|
|
113
|
+
|
|
114
|
+
# mypy
|
|
115
|
+
.mypy_cache/
|
|
116
|
+
|
|
117
|
+
# ruff
|
|
118
|
+
.ruff_cache/
|
|
119
|
+
|
|
120
|
+
# Coverage HTML output
|
|
121
|
+
cov/
|
|
122
|
+
|
|
123
|
+
# IDE settings
|
|
124
|
+
.vscode/
|
|
125
|
+
|
|
126
|
+
# PyCharm project settings
|
|
127
|
+
.idea
|
|
128
|
+
.claude
|
|
129
|
+
|
|
130
|
+
# Local experiments
|
|
131
|
+
sandbox/
|
|
132
|
+
|
|
133
|
+
# Notebook / doctest artifacts
|
|
134
|
+
schedulers.csv
|
|
135
|
+
|
|
136
|
+
# Work clones of tools/publish.py
|
|
137
|
+
.publish/
|
tinto-0.1.0/AUTHORS.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Contributions are welcome, and they are greatly appreciated! Every little bit
|
|
4
|
+
helps, and credit will always be given.
|
|
5
|
+
|
|
6
|
+
You can contribute in many ways:
|
|
7
|
+
|
|
8
|
+
## Types of Contributions
|
|
9
|
+
|
|
10
|
+
### Report Bugs
|
|
11
|
+
|
|
12
|
+
Report bugs at https://github.com/balouf/tinto/issues.
|
|
13
|
+
|
|
14
|
+
If you are reporting a bug, please include:
|
|
15
|
+
|
|
16
|
+
- Your operating system name and version.
|
|
17
|
+
- Any details about your local setup that might be helpful in troubleshooting.
|
|
18
|
+
- Detailed steps to reproduce the bug.
|
|
19
|
+
|
|
20
|
+
### Fix Bugs
|
|
21
|
+
|
|
22
|
+
Look through the GitHub issues for bugs. Anything tagged with "bug" and "help
|
|
23
|
+
wanted" is open to whoever wants to implement it.
|
|
24
|
+
|
|
25
|
+
### Implement Features
|
|
26
|
+
|
|
27
|
+
Look through the GitHub issues for features. Anything tagged with "enhancement"
|
|
28
|
+
and "help wanted" is open to whoever wants to implement it.
|
|
29
|
+
|
|
30
|
+
### Write Documentation
|
|
31
|
+
|
|
32
|
+
Tinto could always use more documentation, whether as part of the
|
|
33
|
+
official Tinto docs, in docstrings, or even on the web in blog posts,
|
|
34
|
+
articles, and such.
|
|
35
|
+
|
|
36
|
+
### Submit Feedback
|
|
37
|
+
|
|
38
|
+
The best way to send feedback is to file an issue at https://github.com/balouf/tinto/issues.
|
|
39
|
+
|
|
40
|
+
If you are proposing a feature:
|
|
41
|
+
|
|
42
|
+
- Explain in detail how it would work.
|
|
43
|
+
- Keep the scope as narrow as possible, to make it easier to implement.
|
|
44
|
+
- Remember that this is a volunteer-driven project, and that contributions
|
|
45
|
+
are welcome :)
|
|
46
|
+
|
|
47
|
+
## Get Started!
|
|
48
|
+
|
|
49
|
+
Ready to contribute? Here's how to set up `tinto` for local development.
|
|
50
|
+
|
|
51
|
+
1. Fork the `tinto` repo on GitHub.
|
|
52
|
+
|
|
53
|
+
2. Clone your fork locally::
|
|
54
|
+
```console
|
|
55
|
+
$ git clone git@github.com:your_name_here/tinto.git
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
3. Install your local copy into a virtualenv. Assuming you have uv installed, this is how you set up your fork for local development:
|
|
59
|
+
```console
|
|
60
|
+
$ cd tinto/
|
|
61
|
+
$ uv sync --all-extras
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
4. Create a branch for local development::
|
|
65
|
+
```console
|
|
66
|
+
$ git checkout -b name-of-your-bugfix-or-feature
|
|
67
|
+
```
|
|
68
|
+
Now you can make your changes locally.
|
|
69
|
+
|
|
70
|
+
5. When you're done making changes, check that your changes pass the
|
|
71
|
+
tests:
|
|
72
|
+
```console
|
|
73
|
+
$ uv run pytest
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
6. Commit your changes and push your branch to GitHub::
|
|
77
|
+
```bash
|
|
78
|
+
$ git add .
|
|
79
|
+
$ git commit -m "Your detailed description of your changes."
|
|
80
|
+
$ git push origin name-of-your-bugfix-or-feature
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
7. Submit a pull request through the GitHub website.
|
|
84
|
+
|
|
85
|
+
## Pull Request Guidelines
|
|
86
|
+
|
|
87
|
+
Before you submit a pull request, check that it meets these guidelines:
|
|
88
|
+
|
|
89
|
+
1. The pull request should include tests.
|
|
90
|
+
2. If the pull request adds functionality, the docs should be updated. Put
|
|
91
|
+
your new functionality into a function with a docstring, and add the
|
|
92
|
+
feature to the list in `.github/README.md` or `HISTORY.md`.
|
|
93
|
+
3. The pull request should work for Python for the versions supported by the package (ideally, the three latest minor CPython versions).
|
|
94
|
+
Make sure that the tests pass for all supported Python versions.
|
|
95
|
+
|
|
96
|
+
## Tips
|
|
97
|
+
|
|
98
|
+
To run a subset of tests:
|
|
99
|
+
```bash
|
|
100
|
+
$ uv run pytest tests.test_tinto
|
|
101
|
+
```
|
tinto-0.1.0/HISTORY.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# History
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (2026-11-11): First release
|
|
4
|
+
|
|
5
|
+
- First release on PyPI.
|
|
6
|
+
|
|
7
|
+
### Coloring dynamics
|
|
8
|
+
|
|
9
|
+
- `graphs`: a Numba-compiled CSR graph, the `line` and `ring` builders,
|
|
10
|
+
and three random generators, each with its edge-list variant: uniform
|
|
11
|
+
labeled tree (`cayley`), Erdős-Rényi `G(n, p)` drawn by geometric
|
|
12
|
+
skipping in O(n + m) (`erdos_renyi`), and bipartite `G(n1, n2, p)`
|
|
13
|
+
(`bipartite`). Graphs are also built from an edge list
|
|
14
|
+
(`edges_to_graph`) or an adjacency matrix (`adja_to_graph`).
|
|
15
|
+
- `guards`: four enabling rules, from the default `color_clash` (a node
|
|
16
|
+
shares its color with a neighbor) to `color_clash_tie`, `color_min`
|
|
17
|
+
and `color_min_tie`.
|
|
18
|
+
- `configs.make`: the coloring configuration, which keeps the set of
|
|
19
|
+
enabled nodes in sync with the colors. Initial colorings may use fewer
|
|
20
|
+
colors than the palette (`Config.color_randomize(k_init)`); without an
|
|
21
|
+
explicit palette, it has `max(k_init, Delta + 1)` colors.
|
|
22
|
+
- `starters`: initial configurations, either on a fixed graph
|
|
23
|
+
(`from_graph`, uniform or random coloring) or on a fresh random graph
|
|
24
|
+
per draw (`from_cayley`, `from_erdos_renyi`, `from_bipartite`); every
|
|
25
|
+
starter takes a palette size `k` and a number of initial colors
|
|
26
|
+
`k_init`.
|
|
27
|
+
- `schedulers`: `shuffled`, `ordered`, `bernoulli` and `independent`.
|
|
28
|
+
- `solvers.make`, with five colorers: `colorer_lowest`, `colorer_next`
|
|
29
|
+
and `colorer_random` pick a free color (smallest, next, uniform);
|
|
30
|
+
`colorer_random_blind` and `colorer_next_blind` skip the neighborhood
|
|
31
|
+
scan and may leave clashes behind, modelling agents that detect a
|
|
32
|
+
conflict locally without seeing which colors are free.
|
|
33
|
+
- `runners`: `simple` runs one trajectory and returns its numbers of
|
|
34
|
+
steps and activations (recolorings); `mc` runs replicas in parallel
|
|
35
|
+
and returns the mean, variance and third central moment of both.
|
|
36
|
+
- The factories are memoized: two calls with the same arguments return
|
|
37
|
+
the same compiled object, so parameter sweeps compile each variant
|
|
38
|
+
once.
|
|
39
|
+
- `io.set_seed` seeds every random generator, Numba's included.
|
|
40
|
+
|
|
41
|
+
### Experiments and estimation
|
|
42
|
+
|
|
43
|
+
- `tinto.Experiment`, `tinto.Iterator` and `tinto.ProductIterator`:
|
|
44
|
+
parameter sweeps (cartesian products with `*`, campaigns merged with
|
|
45
|
+
`+`), with `.run()`, `.plot()`, `.fit()`, `.fit_fractions()`,
|
|
46
|
+
`.report()`, `.residuals()`, `.to_dict()` and `.to_csv()`.
|
|
47
|
+
- `estimate`: weighted least squares on a linear basis (`wls`, `fit`),
|
|
48
|
+
a likelihood-ratio test for a hidden term (`test_extra_term`), and the
|
|
49
|
+
recovery of exact fractions from fitted coefficients (`simplest_in`,
|
|
50
|
+
`recover`, `fit_fractions`, `fractions_table`).
|
|
51
|
+
|
|
52
|
+
### Exact stabilization time
|
|
53
|
+
|
|
54
|
+
Three independent sources for the stabilization time of the
|
|
55
|
+
conflict-guard rule under the random central daemon:
|
|
56
|
+
|
|
57
|
+
- `oracle`, the peak oracle: by the reduction lemma, `T = n - S` with `S`
|
|
58
|
+
the number of peaks of a uniform labeling, so `T` is sampled without
|
|
59
|
+
running the dynamics. `count_peaks`, and parallel samplers on a fixed
|
|
60
|
+
graph (`sample_graph`) or on a fresh random graph per trial
|
|
61
|
+
(`sample_erdos_renyi`, `sample_bipartite`, `sample_cayley`); the
|
|
62
|
+
samples depend on the seed only, not on the number of threads.
|
|
63
|
+
- `exact`: the exact law of the peak count on small graphs, by
|
|
64
|
+
enumeration of all labelings and colorings (`peaks_distribution`,
|
|
65
|
+
colorings up to a permutation of the colors, optional split on whether
|
|
66
|
+
two nodes share their color, optional fixed labeling), its factorial
|
|
67
|
+
moments, and the enumeration of all labeled trees and all graphs on
|
|
68
|
+
`n` nodes.
|
|
69
|
+
- `theory`: closed forms, one submodule per family:
|
|
70
|
+
- `general`: exact mean and variance on any graph (Theorems 1 and 3)
|
|
71
|
+
in rational arithmetic, the mean from a fixed initial coloring, and
|
|
72
|
+
a compiled floating-point monochrome variance for loops over
|
|
73
|
+
millions of graphs;
|
|
74
|
+
- `path_cycle`: generating functions in exact integers, exact laws and
|
|
75
|
+
closed forms;
|
|
76
|
+
- `erdos_renyi`: exact moments and fixed-`p` limit law;
|
|
77
|
+
- `bipartite`: monochrome law and limit mean;
|
|
78
|
+
- `cayley`: pair-degree laws, asymptotic variance slope and the
|
|
79
|
+
generating function of the law on the uniform labeled tree;
|
|
80
|
+
- `star`: law, mean and variance of the star, the graph of largest
|
|
81
|
+
variance.
|
|
82
|
+
|
|
83
|
+
`theory` imports nothing from the simulation side, nor from `exact`;
|
|
84
|
+
`tests/test_independence.py` enforces it.
|
|
85
|
+
|
|
86
|
+
### Documentation
|
|
87
|
+
|
|
88
|
+
- Numpydoc docstrings with doctests on every public module, class and
|
|
89
|
+
function; 100% branch coverage under `NUMBA_DISABLE_JIT=1`.
|
|
90
|
+
- Sphinx reference pages for every module.
|
|
91
|
+
- Two tutorials: `introduction`, a tour of the modules with a
|
|
92
|
+
`verbose_run` helper that walks one step at a time through the
|
|
93
|
+
dynamics, and `basics`, a first set of experiments.
|
|
94
|
+
- Companion notebooks, starting with
|
|
95
|
+
`docs/companion/exact_stabilization_time.ipynb`: the numerical
|
|
96
|
+
statements of the exact stabilization-time report, each checked by
|
|
97
|
+
confronting closed forms, exact enumeration and Monte Carlo (sympy is
|
|
98
|
+
in the `dev` group for its symbolic sections). Notebooks that assert
|
|
99
|
+
checks are stored without outputs; the docs workflow executes them
|
|
100
|
+
before building, so a failing check fails the build.
|
tinto-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: tinto
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: How long does a self-stabilizing graph coloring take to settle? Tinto measures it with a Numba-compiled Monte Carlo over pluggable graphs, guards, schedulers and recoloring rules, down to the variance and skewness of the stabilization time. For the conflict-guard rule under the random central daemon, it also provides exact results.
|
|
5
|
+
Project-URL: Repository, https://github.com/balouf/tinto
|
|
6
|
+
Project-URL: Documentation, https://balouf.github.io/tinto
|
|
7
|
+
Author-email: Fabien Mathieu <fabien.mathieu@normalesup.org>
|
|
8
|
+
Maintainer-email: Fabien Mathieu <fabien.mathieu@normalesup.org>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: AUTHORS.md
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Requires-Dist: numba>=0.65.0
|
|
13
|
+
Requires-Dist: scipy>=1.15.3
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# <img src="../docs/_static/logo.svg" alt="Tinto logo" width="48" valign="middle" /> Tinto
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
[](https://pypi.python.org/pypi/tinto)
|
|
20
|
+
[](https://github.com/balouf/tinto/actions?query=workflow%3Abuild)
|
|
21
|
+
[](https://github.com/balouf/tinto/actions?query=workflow%3Adocs)
|
|
22
|
+
[](https://opensource.org/licenses/MIT)
|
|
23
|
+
[](https://codecov.io/gh/balouf/tinto/tree/main)
|
|
24
|
+
|
|
25
|
+
How long does a self-stabilizing graph coloring take to settle? Tinto measures it with a Numba-compiled Monte Carlo over pluggable graphs, guards, schedulers and recoloring rules, down to the variance and skewness of the stabilization time. For the conflict-guard rule under the random central daemon, it also provides exact results.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
- Free software: MIT
|
|
29
|
+
- Documentation: <https://balouf.github.io/tinto/>.
|
|
30
|
+
- Github: <https://github.com/balouf/tinto>
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- Numba-compiled dynamics: CSR graphs (line, ring, uniform labeled tree,
|
|
36
|
+
Erdős-Rényi `G(n, p)`, bipartite `G(n1, n2, p)`), pluggable guards,
|
|
37
|
+
four schedulers (shuffled, ordered, Bernoulli, independent) and five
|
|
38
|
+
colorers (lowest, next or uniform free color, plus two blind variants
|
|
39
|
+
that may leave clashes behind).
|
|
40
|
+
- Monte-Carlo driver aggregating mean, variance and third central moment
|
|
41
|
+
of both the number of steps and the number of activations before
|
|
42
|
+
stabilization, on a fixed graph or on a fresh random graph per replica.
|
|
43
|
+
- `Experiment` high-level API with cartesian-product sweeps, campaign
|
|
44
|
+
addition, light matplotlib plotting, CSV export, and fits of the
|
|
45
|
+
results (weighted least squares, test for a hidden term, recovery of
|
|
46
|
+
exact fractions).
|
|
47
|
+
- Exact stabilization time of the conflict-guard rule under the random
|
|
48
|
+
central daemon, from three independent sources: the peak oracle, which
|
|
49
|
+
samples it without running the dynamics (`tinto.oracle`), exact
|
|
50
|
+
enumeration on small graphs (`tinto.exact`) and closed forms
|
|
51
|
+
(`tinto.theory`).
|
|
52
|
+
- Companion notebooks that check the numerical statements of the papers.
|
|
53
|
+
- 100% branch-covered by doctest-based examples.
|
|
54
|
+
|
|
55
|
+
## Quickstart
|
|
56
|
+
|
|
57
|
+
Install Tinto:
|
|
58
|
+
|
|
59
|
+
```console
|
|
60
|
+
$ pip install tinto
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Low-level API
|
|
64
|
+
|
|
65
|
+
Drive one trajectory on a line graph:
|
|
66
|
+
|
|
67
|
+
```pycon
|
|
68
|
+
>>> from tinto import graphs, configs, schedulers, solvers, runners
|
|
69
|
+
>>> from tinto.io import set_seed
|
|
70
|
+
>>> set_seed(0)
|
|
71
|
+
>>> Config = configs.make()
|
|
72
|
+
>>> c = Config(graphs.line(20))
|
|
73
|
+
>>> sched = schedulers.shuffled()(c)
|
|
74
|
+
>>> solver = solvers.make()
|
|
75
|
+
>>> steps, activations = runners.simple(c, sched, solver)
|
|
76
|
+
>>> steps > 0
|
|
77
|
+
True
|
|
78
|
+
>>> c.total
|
|
79
|
+
0
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Or Monte-Carlo the moments of both metrics over many replicas:
|
|
83
|
+
|
|
84
|
+
```pycon
|
|
85
|
+
>>> from tinto import starters
|
|
86
|
+
>>> set_seed(0)
|
|
87
|
+
>>> starter = starters.from_graph(Config)(graphs.line(20))
|
|
88
|
+
>>> res = runners.mc(starter, schedulers.shuffled(), solver, n_trials=20)
|
|
89
|
+
>>> mean, var, m3 = res["steps"]
|
|
90
|
+
>>> mean > 0
|
|
91
|
+
True
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### High-level API
|
|
95
|
+
|
|
96
|
+
The `Experiment` class bundles a sweep + the Monte-Carlo runner + plot
|
|
97
|
+
and export helpers. Define an `Iterator` over one parameter, wrap it in
|
|
98
|
+
an `Experiment`, run:
|
|
99
|
+
|
|
100
|
+
```pycon
|
|
101
|
+
>>> from tinto import Experiment, Iterator
|
|
102
|
+
>>> def build_starter(n):
|
|
103
|
+
... return starters.from_graph(Config)(graphs.line(n))
|
|
104
|
+
>>> n_iter = Iterator("starter", [10, 20, 50], name="n", process=build_starter)
|
|
105
|
+
>>> exp = Experiment(
|
|
106
|
+
... "line-sweep",
|
|
107
|
+
... iterator=n_iter,
|
|
108
|
+
... scheduler=schedulers.shuffled(),
|
|
109
|
+
... solver=solver,
|
|
110
|
+
... n_trials=50,
|
|
111
|
+
... )
|
|
112
|
+
>>> _ = exp.run(progress=False)
|
|
113
|
+
>>> exp.results["line-sweep"]["axes"]
|
|
114
|
+
('starter',)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Compose cartesian products with `*` and combine multiple campaigns with
|
|
118
|
+
`+`:
|
|
119
|
+
|
|
120
|
+
```pycon
|
|
121
|
+
>>> kind_iter = Iterator("starter", ["random", "mono"], name="kind")
|
|
122
|
+
>>> # plot or export via exp.plot(x="n", hue="kind") / exp.to_csv(...)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Credits
|
|
126
|
+
|
|
127
|
+
This package was created with [Cookiecutter][CC] and the [Package Helper 3][PH3] project template.
|
|
128
|
+
|
|
129
|
+
[CC]: <https://github.com/audreyr/cookiecutter>
|
|
130
|
+
[PH3]: <https://balouf.github.io/package-helper-3/>
|
tinto-0.1.0/citation.cff
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
|
|
2
|
+
cff-version: 1.2.0
|
|
3
|
+
title: Tinto
|
|
4
|
+
message: >-
|
|
5
|
+
If you use this software, please cite it using the
|
|
6
|
+
metadata from this file.
|
|
7
|
+
type: software
|
|
8
|
+
version: 0.1.0
|
|
9
|
+
date-released: "2026-11-11"
|
|
10
|
+
authors:
|
|
11
|
+
- family-names: Mathieu
|
|
12
|
+
given-names: Fabien
|
|
13
|
+
email: fabien.mathieu@normalesup.org
|
|
14
|
+
repository-code: "https://github.com/balouf/tinto/"
|
|
15
|
+
url: "https://balouf.github.io/tinto/"
|
|
16
|
+
abstract: "How long does a self-stabilizing graph coloring take to settle? Tinto measures it with a Numba-compiled Monte Carlo over pluggable graphs, guards, schedulers and recoloring rules, down to the variance and skewness of the stabilization time. For the conflict-guard rule under the random central daemon, it also provides exact results."
|
|
17
|
+
license: MIT
|
tinto-0.1.0/conftest.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Pytest configuration for the Tinto test suite."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
# Disable numba JIT so that coverage can instrument the bodies of @jitclass /
|
|
6
|
+
# @njit functions. Must be set before numba is imported — conftest.py runs
|
|
7
|
+
# before any test or project module. CI mirrors this via the NUMBA_DISABLE_JIT
|
|
8
|
+
# env var in .github/workflows/build.yml.
|
|
9
|
+
os.environ.setdefault("NUMBA_DISABLE_JIT", "1")
|
|
10
|
+
|
|
11
|
+
# Headless matplotlib backend for .plot() doctests. Must be set before any
|
|
12
|
+
# matplotlib import; MPLBACKEND is the official env var for that.
|
|
13
|
+
os.environ.setdefault("MPLBACKEND", "Agg")
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
|
|
17
|
+
# NumPy 2.0 changed scalar repr: np.int32(2) now prints as "np.int32(2)"
|
|
18
|
+
# instead of "2", which breaks doctests that were written against JIT output
|
|
19
|
+
# (plain Python ints). The legacy="1.25" flag restores the old repr.
|
|
20
|
+
np.set_printoptions(legacy="1.25")
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" role="img" aria-label="Tinto logo: 5-cycle with a valid 3-coloring">
|
|
3
|
+
<title>Tinto</title>
|
|
4
|
+
<!-- Pentagon (5-cycle) with a proper 3-coloring: R, G, B, R, G. -->
|
|
5
|
+
<!-- Vertex positions, regular pentagon centered at (50, 50), radius 35. -->
|
|
6
|
+
<g stroke="#2f3437" stroke-width="3" stroke-linecap="round">
|
|
7
|
+
<line x1="50" y1="15" x2="16.7" y2="39.2"/>
|
|
8
|
+
<line x1="16.7" y1="39.2" x2="29.4" y2="78.3"/>
|
|
9
|
+
<line x1="29.4" y1="78.3" x2="70.6" y2="78.3"/>
|
|
10
|
+
<line x1="70.6" y1="78.3" x2="83.3" y2="39.2"/>
|
|
11
|
+
<line x1="83.3" y1="39.2" x2="50" y2="15"/>
|
|
12
|
+
</g>
|
|
13
|
+
<g stroke="#2f3437" stroke-width="2.5">
|
|
14
|
+
<circle cx="50" cy="15" r="11" fill="#d62728"/>
|
|
15
|
+
<circle cx="16.7" cy="39.2" r="11" fill="#2ca02c"/>
|
|
16
|
+
<circle cx="29.4" cy="78.3" r="11" fill="#1f77b4"/>
|
|
17
|
+
<circle cx="70.6" cy="78.3" r="11" fill="#d62728"/>
|
|
18
|
+
<circle cx="83.3" cy="39.2" r="11" fill="#2ca02c"/>
|
|
19
|
+
</g>
|
|
20
|
+
</svg>
|