Skip to content

Commit ad0f24b

Browse files
committed
chore: improve readme
1 parent 1355020 commit ad0f24b

File tree

2 files changed

+253
-36
lines changed

2 files changed

+253
-36
lines changed

CITATION.cff

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
cff-version: 1.2.0
2+
message: >-
3+
If you use this software, please cite it using the metadata below.
4+
title: min-ratio-cycle
5+
abstract: >-
6+
Minimum cost-to-time ratio cycle solver with NumPy acceleration and exact
7+
Stern–Brocot search for integer inputs.
8+
version: 0.1.0
9+
license: MIT
10+
type: software
11+
authors:
12+
- family-names: Ribeiro
13+
given-names: Diogo
14+
affiliation: ESMAD – Instituto Politécnico do Porto
15+
16+
orcid: "https://orcid.org/0009-0001-2022-7072"
17+
keywords:
18+
- graph algorithms
19+
- minimum ratio cycle
20+
- parametric search
21+
- Bellman–Ford
22+
- Stern–Brocot
23+
- Python
24+
- NumPy
25+
26+
preferred-citation:
27+
type: software
28+
title: min-ratio-cycle
29+
version: 0.1.0
30+
authors:
31+
- family-names: Ribeiro
32+
given-names: Diogo
33+
affiliation: ESMAD – Instituto Politécnico do Porto
34+
35+
orcid: "https://orcid.org/0009-0001-2022-7072"
36+
license: MIT
37+
38+
references:
39+
- type: article
40+
title: "Improved Algorithms for Computing the Cycle of Minimum Cost-to-Time Ratio in Directed Graphs"
41+
authors:
42+
- family-names: Bringmann
43+
given-names: Karl
44+
- family-names: Hansen
45+
given-names: Thomas Dueholm
46+
- family-names: Krinninger
47+
given-names: Sebastian
48+
year: 2017
49+
journal: arXiv
50+
identifiers:
51+
- type: arXiv
52+
value: "1704.08122"
53+
notes: "Accepted to ICALP 2017"

README.md

Lines changed: 200 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,248 @@
1-
# Min Ratio Cycle Solver
1+
# min-ratio-cycle
22

33
An optimized Python library for finding the **minimum cost-to-time ratio cycle** in a directed graph.
44

5-
## Features
5+
> Lawler-style parametric search with NumPy-accelerated negative‑cycle detection and an exact Stern–Brocot mode for integer weights.
66
7-
- Lawler parametric search with NumPy-accelerated Bellman–Ford relaxations
8-
- Stern–Brocot exact mode for integer weights
9-
- Comprehensive pre- and post-solve validation of topology, weight ranges, conditioning, and ratio correctness
10-
- Rich exception hierarchy with recovery hints (`GraphStructureError`, `NumericalInstabilityError`, `ResourceExhaustionError`)
11-
- Resource limits and graceful degradation with exact-mode fallbacks or relaxed tolerances
12-
- Advanced analytics for sensitivity studies, stability region estimation, confidence intervals, convergence rates, and statistical comparisons
13-
- Static and interactive visualisation helpers
14-
- Benchmark suite with DIMACS loaders, regression baselines, and optional NetworkX comparisons
15-
- Iterable solver results for intuitive tuple unpacking `(cycle, cost, time, ratio)`
7+
---
8+
9+
## Table of Contents
10+
11+
- [min-ratio-cycle](#min-ratio-cycle)
12+
- [Table of Contents](#table-of-contents)
13+
- [Highlights](#highlights)
14+
- [Installation](#installation)
15+
- [Quick Start](#quick-start)
16+
- [Analytics \& Visualization](#analytics--visualization)
17+
- [How It Works (Short)](#how-it-works-short)
18+
- [Background \& References](#background--references)
19+
- [Benchmarks](#benchmarks)
20+
- [Documentation](#documentation)
21+
- [Testing \& Quality](#testing--quality)
22+
- [Development](#development)
23+
- [Troubleshooting](#troubleshooting)
24+
- [License](#license)
25+
- [Maintainer](#maintainer)
26+
27+
---
28+
29+
## Highlights
30+
31+
* **Parametric search** over $\lambda$ with fast relaxations on weights $w_\lambda(e) = c(e) - \lambda\,t(e)$.
32+
* **Exact mode** via Stern–Brocot for integer inputs (returns a rational $\lambda^*$).
33+
* **Robustness**: topology and weight validation, clear exceptions, recovery hints.
34+
* **Analytics**: sensitivity studies, stability regions, simple confidence intervals.
35+
* **Visualization helpers** for cycles/ratios.
36+
* **Benchmarks** with optional NetworkX comparisons.
37+
* **Ergonomic results**: iterable `(cycle, cost, time, ratio)` pattern.
38+
39+
---
1640

1741
## Installation
1842

43+
This project uses Poetry.
44+
1945
```bash
2046
poetry install
2147
```
2248

23-
## Quick start
49+
Tips
50+
51+
* Prefer a system BLAS (OpenBLAS/MKL) for faster NumPy.
52+
* Enable pre-commit hooks after install:
53+
54+
```bash
55+
poetry run pre-commit install
56+
```
57+
58+
---
59+
60+
## Quick Start
2461

2562
```python
26-
from min_ratio_cycle.solver import MinRatioCycleSolver, Edge
63+
# Example API (module namespace: min_ratio_cycle)
64+
from min_ratio_cycle.solver import MinRatioCycleSolver
2765

28-
solver = MinRatioCycleSolver(3)
29-
solver.add_edges([
30-
Edge(0, 1, cost=2, time=1),
31-
Edge(1, 2, cost=3, time=2),
32-
Edge(2, 0, cost=1, time=1),
33-
])
66+
# Create a 3-node directed graph
67+
solver = MinRatioCycleSolver(n_nodes=3)
3468

69+
# Add edges (u -> v) with cost and time
70+
solver.add_edge(0, 1, cost=2, time=1)
71+
solver.add_edge(1, 2, cost=3, time=2)
72+
solver.add_edge(2, 0, cost=1, time=1)
73+
74+
# Solve
3575
cycle, cost, time, ratio = solver.solve()
36-
print(cycle, ratio)
76+
print("Cycle:", cycle)
77+
print("Cost:", cost, " Time:", time, " Ratio:", ratio)
3778
```
3879

39-
## Analytics
80+
* `cycle`: list of node indices forming the minimum ratio cycle.
81+
* `ratio = cost / time`: minimum cost-per-time among all directed cycles.
82+
83+
> If your graph is strictly integer-weighted (costs and times), you can enable the exact mode to avoid floating-point drift.
84+
85+
```python
86+
cycle, cost, time, ratio = solver.solve(exact=True) # Stern–Brocot search
87+
```
88+
89+
---
90+
91+
## Analytics & Visualization
92+
93+
Sensitivity and simple confidence intervals:
4094

4195
```python
4296
from min_ratio_cycle.analytics import sensitivity_analysis, confidence_interval
4397

44-
perturb = {(0, 1): 0.1}
98+
# +10% cost on edge (0 -> 1)
99+
perturb = {(0, 1): {"cost": +0.10}}
45100
summary = sensitivity_analysis(solver, perturb)
46-
ci = confidence_interval([ratio for _ in range(5)])
101+
ci = confidence_interval(samples=[ratio for _ in range(10)])
47102
```
48103

49-
## Visualisation
104+
Visualize solution:
50105

51106
```python
52-
result = solver.solve()
107+
result = solver.solve(return_object=True)
53108
result.visualize_solution(show_cycle=True)
54109
```
55110

56-
## Benchmarking
111+
---
112+
113+
## How It Works (Short)
114+
115+
We search for the scalar parameter $\lambda$ such that no directed cycle has negative **mean cost** in the reweighted graph $G_\lambda$, where each edge weight is
116+
$\; w_\lambda(e) = c(e) - \lambda\,t(e).$
117+
118+
* For a given $\lambda$, we run negative‑cycle detection (Bellman–Ford style relaxations) on $w_\lambda$.
119+
* The minimum feasible $\lambda$ with **no** negative cycle equals the **minimum cost-to-time ratio** over all cycles.
120+
* For integer inputs, an **exact** Stern–Brocot search avoids floating error and returns $\lambda^*$ as a rational.
121+
122+
This design offers practical speed (vectorized relaxations) and correctness (exact arithmetic when applicable).
123+
124+
---
125+
126+
## Background & References
127+
128+
This library is based on and follows the problem formulation from:
129+
130+
> **Karl Bringmann, Thomas Dueholm Hansen, Sebastian Krinninger** (ICALP 2017; arXiv:1704.08122),
131+
> *Improved Algorithms for Computing the Cycle of Minimum Cost‑to‑Time Ratio in Directed Graphs.*
132+
133+
**Core ideas used here**
134+
135+
* Adopt the **parametric reduction**: reweight edges as $c - \lambda t$ and test for negative cycles.
136+
* Implement a practical **decision oracle** with NumPy‑accelerated relaxations.
137+
* Use **bisection** for $\lambda$ in floating mode and **Stern–Brocot** in exact integer mode.
138+
139+
**BibTeX** (please cite if you use this library in research):
140+
141+
```bibtex
142+
@article{bringmann2017improved,
143+
title = {Improved Algorithms for Computing the Cycle of Minimum Cost-to-Time Ratio in Directed Graphs},
144+
author = {Karl Bringmann and Thomas Dueholm Hansen and Sebastian Krinninger},
145+
journal = {arXiv:1704.08122},
146+
year = {2017},
147+
note = {Accepted to ICALP 2017}
148+
}
149+
```
150+
151+
---
152+
153+
## Benchmarks
154+
155+
We include pytest markers to separate performance runs and comparisons.
156+
157+
```bash
158+
# Micro-benchmarks
159+
poetry run pytest -m benchmark
160+
161+
# Optional: parallelize
162+
poetry run pytest -n auto -m benchmark
163+
```
164+
165+
Programmatic entry:
57166

58167
```python
59168
from min_ratio_cycle.benchmarks import benchmark_solver
60-
61-
runtime, ratio = benchmark_solver(solver)
169+
runtime_s, ratio = benchmark_solver(solver)
170+
print(f"{runtime_s:.6f}s -> ratio={ratio}")
62171
```
63172

173+
Tips
174+
175+
* Pin NumPy and BLAS for stable timing.
176+
* For very large graphs, consider tighter early‑exit tolerances.
177+
178+
---
179+
64180
## Documentation
65181

66-
The full user and API guides live in `docs/`. Build the Sphinx documentation:
182+
Sphinx docs live under `docs/`. Build locally:
67183

68184
```bash
69185
poetry run sphinx-build -b html docs docs/_build/html
70186
```
71187

72-
## Testing
188+
A Read the Docs configuration is included for easy hosting.
189+
190+
---
191+
192+
## Testing & Quality
193+
194+
We use `pytest`, property-based tests, coverage, type checks, linting, and security scans (configured in `pyproject.toml`).
73195

74196
```bash
75-
poetry run pytest
197+
# Unit & property tests
198+
poetry run pytest --cov=min_ratio_cycle
199+
200+
# Type checks
201+
poetry run mypy min_ratio_cycle
202+
203+
# Style & lint
204+
poetry run black . && poetry run isort .
205+
poetry run flake8 .
206+
207+
# Security scan
208+
poetry run bandit -r min_ratio_cycle
209+
```
210+
211+
Enable hooks:
212+
213+
```bash
214+
poetry run pre-commit install
76215
```
77216

217+
---
218+
219+
## Development
220+
221+
* Package module: `min_ratio_cycle/`
222+
* Tests: `tests/` with markers `slow`, `benchmark`, `property`, `integration`
223+
* Build/publish: Poetry; convenience targets in `Makefile`
224+
225+
---
226+
227+
## Troubleshooting
228+
229+
* **Floating‑point sensitivity**: use `exact=True` for integer data.
230+
* **Non‑positive times**: all `time` values must be strictly positive; validation fails early.
231+
* **Large graphs**: ensure sufficient RAM; reduce warmups in benchmarks.
232+
* **Unexpected ratios**: check units and ensure no edge has negative time.
233+
234+
---
235+
236+
## License
237+
238+
MIT — see `LICENSE`.
239+
240+
---
241+
78242
## Maintainer
79243

80-
Diogo Ribeiro (DiogoRibeiro7)
81-
ESMAD - Instituto Politécnico do Porto
82-
83-
Professional: [email protected]
84-
ORCID: https://orcid.org/0009-0001-2022-7072
244+
**Diogo Ribeiro (DiogoRibeiro7)**
245+
ESMAD Instituto Politécnico do Porto
246+
247+
Professional: [[email protected]](mailto:[email protected])
248+
ORCID: [https://orcid.org/0009-0001-2022-7072](https://orcid.org/0009-0001-2022-7072)

0 commit comments

Comments
 (0)