algorithm-discovery-engine 1.0.0__py3-none-any.whl

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.
@@ -0,0 +1,251 @@
1
+ """Built-in mathematical hypotheses.
2
+
3
+ Each hypothesis inspects an :class:`IntegerSequence` and reports a confidence
4
+ in [0, 1] plus an optional next-term prediction.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from fractions import Fraction
10
+
11
+ from algo_discovery.models import HypothesisScore, IntegerSequence
12
+
13
+
14
+ class BaseHypothesis:
15
+ """Abstract base for a sequence hypothesis."""
16
+
17
+ name = "base"
18
+ description = ""
19
+
20
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
21
+ raise NotImplementedError
22
+
23
+
24
+ class ConstantHypothesis(BaseHypothesis):
25
+ """All terms are equal."""
26
+
27
+ name = "constant"
28
+
29
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
30
+ equal = all(t == seq[0] for t in seq.terms)
31
+ conf = 1.0 if equal else 0.0
32
+ pred = seq[0] if equal else None
33
+ return HypothesisScore(self.name, conf, "c, c, c, ...", pred)
34
+
35
+
36
+ class ArithmeticHypothesis(BaseHypothesis):
37
+ """Constant first difference (a, a+d, a+2d, ...)."""
38
+
39
+ name = "arithmetic"
40
+
41
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
42
+ diffs = {seq[i + 1] - seq[i] for i in range(len(seq) - 1)}
43
+ if len(diffs) == 1:
44
+ d = next(iter(diffs))
45
+ return HypothesisScore(
46
+ self.name, 1.0, f"a[i] = a[0] + {d}·i", seq[-1] + d
47
+ )
48
+ return HypothesisScore(self.name, 0.0)
49
+
50
+
51
+ class GeometricHypothesis(BaseHypothesis):
52
+ """Constant ratio (a, a·r, a·r², ...) over the rationals."""
53
+
54
+ name = "geometric"
55
+
56
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
57
+ if any(t == 0 for t in seq.terms):
58
+ return HypothesisScore(self.name, 0.0)
59
+ ratios = {
60
+ Fraction(seq[i + 1], seq[i]) for i in range(len(seq) - 1)
61
+ }
62
+ if len(ratios) == 1:
63
+ r = next(iter(ratios))
64
+ num, den = r.numerator, r.denominator
65
+ pred = seq[-1] * num // den if (seq[-1] * num) % den == 0 else None
66
+ return HypothesisScore(
67
+ self.name, 1.0, f"a[i] = a[0] · ({num}/{den})^i", pred,
68
+ )
69
+ return HypothesisScore(self.name, 0.0)
70
+
71
+
72
+ class QuadraticHypothesis(BaseHypothesis):
73
+ """Constant non-zero second difference => degree-2 polynomial in the index."""
74
+
75
+ name = "quadratic"
76
+
77
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
78
+ if len(seq) < 3:
79
+ return HypothesisScore(self.name, 0.0)
80
+ first = [seq[i + 1] - seq[i] for i in range(len(seq) - 1)]
81
+ second = {first[i + 1] - first[i] for i in range(len(first) - 1)}
82
+ if len(second) == 1:
83
+ d2 = next(iter(second))
84
+ if d2 == 0:
85
+ # zero curvature is just a linear (arithmetic) pattern
86
+ return HypothesisScore(self.name, 0.0)
87
+ ndiff = first[-1] + d2
88
+ return HypothesisScore(self.name, 1.0, f"Δ² = {d2}", seq[-1] + ndiff)
89
+ return HypothesisScore(self.name, 0.0)
90
+
91
+
92
+ class PowerOfTwoHypothesis(BaseHypothesis):
93
+ """Terms are exact powers of 2 (a[i] = 2^k)."""
94
+
95
+ name = "powers-of-two"
96
+
97
+ @staticmethod
98
+ def _is_power_of_two(value: int) -> bool:
99
+ return value > 0 and (value & (value - 1)) == 0
100
+
101
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
102
+ if any(not self._is_power_of_two(t) for t in seq.terms):
103
+ return HypothesisScore(self.name, 0.0)
104
+ # consecutive powers of 2: each term is double the previous
105
+ consecutive = all(
106
+ seq.terms[i + 1] == 2 * seq.terms[i] for i in range(len(seq) - 1)
107
+ )
108
+ return HypothesisScore(self.name, 1.0, "powers of 2",
109
+ 2 * seq[-1] if consecutive else None)
110
+
111
+
112
+ class CubicHypothesis(BaseHypothesis):
113
+ """Constant third difference => degree-3 polynomial in the index."""
114
+
115
+ name = "cubic"
116
+
117
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
118
+ if len(seq) < 4:
119
+ return HypothesisScore(self.name, 0.0)
120
+
121
+ def diffs(values: list[int]) -> list[int]:
122
+ return [values[i + 1] - values[i] for i in range(len(values) - 1)]
123
+
124
+ first = diffs(list(seq.terms))
125
+ second = diffs(first)
126
+ third = diffs(second)
127
+ if len(set(third)) == 1:
128
+ d3 = third[0]
129
+ if d3 == 0:
130
+ return HypothesisScore(self.name, 0.0)
131
+ nd2 = second[-1] + d3
132
+ nd1 = first[-1] + nd2
133
+ return HypothesisScore(self.name, 1.0, f"Δ³ = {d3}", seq[-1] + nd1)
134
+ return HypothesisScore(self.name, 0.0)
135
+
136
+
137
+ class FibonacciLikeHypothesis(BaseHypothesis):
138
+ """Every term (past the first two) equals the sum of its two predecessors."""
139
+
140
+ name = "fibonacci-like"
141
+
142
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
143
+ terms = seq.terms
144
+ for i in range(2, len(terms)):
145
+ if terms[i] != terms[i - 1] + terms[i - 2]:
146
+ return HypothesisScore(self.name, 0.0)
147
+ return HypothesisScore(self.name, 1.0, "a[i] = a[i-1] + a[i-2]",
148
+ terms[-1] + terms[-2])
149
+
150
+
151
+ class RecurrenceLinearHypothesis(BaseHypothesis):
152
+ """Best-fit linear recurrence a[i] = p·a[i-1] + q (solve exactly when possible)."""
153
+
154
+ name = "linear-recurrence"
155
+
156
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
157
+ terms = seq.terms
158
+ # solve for (p, q) from the first two constraints
159
+ # a1 = p*a0 + q ; a2 = p*a1 + q => p = (a2 - a1)/(a1 - a0)
160
+ denom = terms[1] - terms[0]
161
+ if denom == 0:
162
+ if terms[2] == terms[1]:
163
+ return HypothesisScore(
164
+ self.name, 1.0, "a[i] = a[i-1] (constant)", terms[-1]
165
+ )
166
+ return HypothesisScore(self.name, 0.0)
167
+ if (terms[2] - terms[1]) % denom != 0:
168
+ return HypothesisScore(self.name, 0.0)
169
+ p = (terms[2] - terms[1]) // denom
170
+ q = terms[1] - p * terms[0]
171
+ for i in range(3, len(terms)):
172
+ if terms[i] != p * terms[i - 1] + q:
173
+ return HypothesisScore(self.name, 0.0)
174
+ return HypothesisScore(
175
+ self.name, 1.0, f"a[i] = {p}·a[i-1] + {q}",
176
+ p * terms[-1] + q,
177
+ )
178
+
179
+
180
+ class PrimeHypothesis(BaseHypothesis):
181
+ """Terms are consecutive (or non-decreasing) primes."""
182
+
183
+ name = "primes"
184
+
185
+ @staticmethod
186
+ def _is_prime(value: int) -> bool:
187
+ if value < 2:
188
+ return False
189
+ if value < 4:
190
+ return True
191
+ if value % 2 == 0 or value % 3 == 0:
192
+ return False
193
+ i = 5
194
+ while i * i <= value:
195
+ if value % i == 0 or value % (i + 2) == 0:
196
+ return False
197
+ i += 6
198
+ return True
199
+
200
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
201
+ if any(not self._is_prime(t) for t in seq.terms):
202
+ return HypothesisScore(self.name, 0.0)
203
+ consecutive = all(
204
+ all(not self._is_prime(c) for c in range(seq[i] + 1, seq[i + 1]))
205
+ for i in range(len(seq) - 1)
206
+ ) if all(seq[i] < seq[i + 1] for i in range(len(seq) - 1)) else False
207
+ conf = 1.0 if consecutive else 0.7
208
+ return HypothesisScore(self.name, conf, "all terms are prime")
209
+
210
+
211
+ class AlternatingHypothesis(BaseHypothesis):
212
+ """Strictly alternating signs with non-decreasing magnitudes."""
213
+
214
+ name = "alternating"
215
+
216
+ def detect(self, seq: IntegerSequence) -> HypothesisScore:
217
+ mags = [abs(t) for t in seq.terms]
218
+ signs = [t > 0 for t in seq.terms]
219
+ strictly_alt = all(signs[i] != signs[i + 1] for i in range(len(signs) - 1))
220
+ monotone_mag = all(mags[i] <= mags[i + 1] for i in range(len(mags) - 1))
221
+ conf = 1.0 if strictly_alt and monotone_mag else 0.0
222
+ mag_growth = mags[-1] - mags[-2]
223
+ pred = seq[-1] - mag_growth if signs[-1] else seq[-1] + mag_growth
224
+ return HypothesisScore(self.name, conf, "sign alternates", pred)
225
+
226
+
227
+ ALL_HYPOTHESES: tuple[type[BaseHypothesis], ...] = (
228
+ ConstantHypothesis,
229
+ ArithmeticHypothesis,
230
+ GeometricHypothesis,
231
+ QuadraticHypothesis,
232
+ CubicHypothesis,
233
+ PowerOfTwoHypothesis,
234
+ FibonacciLikeHypothesis,
235
+ RecurrenceLinearHypothesis,
236
+ PrimeHypothesis,
237
+ AlternatingHypothesis,
238
+ )
239
+
240
+
241
+ def build_hypotheses(extra: list[BaseHypothesis] | None = None) -> list[BaseHypothesis]:
242
+ """Instantiate the standard hypothesis set plus any extras."""
243
+ instances: list[BaseHypothesis] = [cls() for cls in ALL_HYPOTHESES]
244
+ if extra:
245
+ instances.extend(extra)
246
+ return instances
247
+
248
+
249
+ def describe(hypothesis: BaseHypothesis) -> str:
250
+ """Human description used by the CLI/reporter."""
251
+ return f"{hypothesis.name}: {hypothesis.description or hypothesis.name}"
@@ -0,0 +1,63 @@
1
+ """Core data model for sequences and discovery results."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+
7
+
8
+ @dataclass(frozen=True)
9
+ class IntegerSequence:
10
+ """An immutable integer sequence.
11
+
12
+ A sequence of at least three integers (the framework needs enough
13
+ evidence to distinguish hypotheses). Empty and length-1/2 sequences are
14
+ rejected at construction.
15
+ """
16
+
17
+ terms: tuple[int, ...]
18
+
19
+ def __init__(self, terms: tuple[int, ...] | list[int]) -> None:
20
+ if len(terms) < 3:
21
+ raise ValueError("a sequence needs at least 3 terms")
22
+ object.__setattr__(self, "terms", tuple(terms))
23
+
24
+ def __len__(self) -> int:
25
+ return len(self.terms)
26
+
27
+ def __getitem__(self, index: int) -> int:
28
+ return self.terms[index]
29
+
30
+ @property
31
+ def span(self) -> int:
32
+ """max - min over the whole sequence (a crude trend measure)."""
33
+ return max(self.terms) - min(self.terms)
34
+
35
+
36
+ @dataclass
37
+ class HypothesisScore:
38
+ """Confidence of a single hypothesis against a sequence."""
39
+
40
+ name: str
41
+ confidence: float
42
+ detail: str = ""
43
+ prediction: int | None = None
44
+
45
+ def __post_init__(self) -> None:
46
+ self.confidence = round(max(0.0, min(1.0, self.confidence)), 4)
47
+
48
+
49
+ @dataclass
50
+ class DiscoveryResult:
51
+ """Ranked set of hypotheses for one sequence."""
52
+
53
+ sequence: IntegerSequence
54
+ scores: list[HypothesisScore] = field(default_factory=list)
55
+
56
+ @property
57
+ def best(self) -> HypothesisScore | None:
58
+ ranked = self.ranked
59
+ return ranked[0] if ranked else None
60
+
61
+ @property
62
+ def ranked(self) -> list[HypothesisScore]:
63
+ return sorted(self.scores, key=lambda s: s.confidence, reverse=True)
@@ -0,0 +1,287 @@
1
+ Metadata-Version: 2.5
2
+ Name: algorithm-discovery-engine
3
+ Version: 1.0.0
4
+ Summary: Multi-language algorithms & data structures solving engine (Java, C++, Rust, Python) with cross-language benchmarks and a local AI synthesizer that rediscovers algorithms from examples.
5
+ Author: dsk-dev-ai
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Keywords: ai,algorithm-discovery,algorithms,automated-discovery,benchmark,cpp,data-structures,developer-tools,education,java,learning,machine-learning,open-source,python,rust,scientific-computing,sequence-analysis,synthesizer
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Education
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: C++
15
+ Classifier: Programming Language :: Java
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Rust
18
+ Classifier: Topic :: Education
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+
24
+ <div align="center">
25
+
26
+ # algorithm-discovery-engine
27
+
28
+ **One catalog, four languages, zero dependencies — and a synthesizer that rediscovers the algorithms for you.**
29
+
30
+ [![CI](https://github.com/dsk-dev-ai/algorithm-discovery-engine/actions/workflows/ci.yml/badge.svg)](https://github.com/dsk-dev-ai/algorithm-discovery-engine/actions/workflows/ci.yml)
31
+ [![Stars](https://img.shields.io/github/stars/dsk-dev-ai/algorithm-discovery-engine?style=flat-square&logo=github&logoColor=white)](https://github.com/dsk-dev-ai/algorithm-discovery-engine/stargazers)
32
+ [![Forks](https://img.shields.io/github/forks/dsk-dev-ai/algorithm-discovery-engine?style=flat-square&logo=github&logoColor=white)](https://github.com/dsk-dev-ai/algorithm-discovery-engine/forks)
33
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
34
+ [![Last commit](https://img.shields.io/github/last-commit/dsk-dev-ai/algorithm-discovery-engine?style=flat-square&logo=git&logoColor=white)]()
35
+ [![Docs](https://img.shields.io/badge/docs-live-blue?style=flat-square&logo=materialformkdocs&logoColor=white)](https://dsk-dev-ai.github.io/algorithm-discovery-engine/)
36
+ [![GHCR](https://img.shields.io/badge/container-ghcr.io-lightgrey?style=flat-square&logo=docker&logoColor=white)](https://github.com/dsk-dev-ai/algorithm-discovery-engine/pkgs/container/algorithm-discovery-engine)
37
+ [![GUI](https://img.shields.io/badge/available-gui_tkinter-blueviolet?style=flat-square)](#desktop-gui)
38
+ [![Sponsor](https://img.shields.io/badge/%E2%9D%A4%EF%B8%8F-Sponsor-red?style=flat-square&logo=githubsponsors&logoColor=white)](https://github.com/sponsors/dsk-dev-ai)
39
+
40
+ **Python** · **Java** · **C++** · **Rust**
41
+
42
+ <img src=".github/social-preview.png" alt="algorithm-discovery-engine social preview" width="100%" />
43
+
44
+ </div>
45
+
46
+ ---
47
+
48
+ **The same algorithms and data structures, solved, tested, and benchmarked in Java, C++,
49
+ Rust, and Python**, with one `catalog/problems.json` as the single source of truth and
50
+ byte-identical generated test vectors across every language. On top sits a local
51
+ **algorithm synthesizer** that discovers verified algorithms (Kadane, buy-and-sell, jump
52
+ game) from input/output examples alone — no APIs, no model calls.
53
+
54
+ ## Features
55
+
56
+ - **Multi-language solving engine** — 10 algorithms + 6 data structures implemented in
57
+ Java, C++17, Rust, and Python (regular + optimized advanced tiers).
58
+ - **Cross-language benchmarks** — a single harness times all four tiers; compare
59
+ strategies (Java's hash-map two-sum vs. the quadratic scans in C++/Rust).
60
+ - **Local algorithm synthesizer** — grammar-based search + strategy templates that
61
+ rediscover known algorithms and surface novel ones, fuzz-verified out-of-sample.
62
+ - **Automated mathematical pattern discovery** — the original engine: feed in a
63
+ sequence, get ranked hypotheses (arithmetic, geometric, quadratic, Fibonacci-like) and
64
+ next-term predictions.
65
+ - **Zero dependencies per language** — no framework, no package, no JIT magic; pure
66
+ standard library in all four tiers.
67
+ - **Desktop GUI** — a Tkinter app (`python -m gui`) built on the standard library only;
68
+ core logic is headless-tested in CI.
69
+ - **Generated-then-committed test vectors** — identical tests enforced by CI in every
70
+ language; a single `--check` keeps them in sync with the catalog.
71
+ - **CI-green by default** — grid of Python 3.10–3.13, Java 21, GCC C++17, stable Rust,
72
+ discovery-smoke, GUI-core smoke, and a strict docs build.
73
+
74
+ ## Quick start
75
+
76
+ ```sh
77
+ git clone https://github.com/dsk-dev-ai/algorithm-discovery-engine.git
78
+ cd algorithm-discovery-engine
79
+
80
+ python engine/runner.py test # build + run the catalog suite in all 4 languages
81
+ python engine/runner.py bench # benchmark all tiers, side by side
82
+ python engine/runner.py discover # synthesize + verify algorithms from examples
83
+ python -m gui # open the desktop app
84
+ ```
85
+
86
+ No install required — Python ≥ 3.10 and (for the non-Python tiers) a JDK, a C++17
87
+ compiler, and the Rust toolchain.
88
+
89
+ ## The multi-language engine
90
+
91
+ ### Catalog
92
+
93
+ `catalog/problems.json` is the source of truth. Every algorithm and structure carries a
94
+ shared test vector set asserted in **all four languages**.
95
+
96
+ | Algorithms (10) | Data structures (6) |
97
+ | -------------------------------------------------------- | ------------------------------------------------ |
98
+ | `two_sum`, `binary_search`, `merge_sort`, `quick_sort` | `stack`, `queue`, `linked_list`, `bst` |
99
+ | `max_subarray`, `lcs`, `knapsack_01`, `edit_distance` | `trie`, `min_heap` |
100
+ | `graph_bfs`, `graph_dfs` | |
101
+
102
+ ### Language tiers
103
+
104
+ ```mermaid
105
+ flowchart LR
106
+ C[ catalog/problems.json ] --> G[ engine/gen_tests.py ]
107
+ G --> J[Java tests] & P[Python tests] & R[Rust tests] & X[C++ tests]
108
+ J -. reference impl .-> P
109
+ ```
110
+
111
+ | Tier | Location | Approach |
112
+ | ------ | ------------------------ | ---------------------------------------------------- |
113
+ | Java | `languages/java/` | OO reference implementations |
114
+ | C++ | `languages/cpp/` | modern C++17, RAII, iterators |
115
+ | Rust | `languages/rust/` | ownership-safe, zero dependencies |
116
+ | Python | `src/ads/` | regular + advanced (`*_advanced`, mypy strict) |
117
+
118
+ ### Sample benchmark (microseconds, lower is better)
119
+
120
+ ```
121
+ algorithm Python Java C++ Rust
122
+ merge_sort 928,850 85,358 66,972 39,647
123
+ quick_sort 702,918 41,562 22,942 17,610
124
+ max_subarray 444,168 17,881 9,702 78
125
+ ```
126
+
127
+ > Languages may pick different strategies for the same problem (Java's `two_sum` uses a
128
+ > hash map; C++/Rust use a quadratic scan) — the table is a trade-off showcase, not an
129
+ > exact contest.
130
+
131
+ ## The synthesizer (the interesting part)
132
+
133
+ `src/synth/` searches for candidate algorithms from input/output examples and verifies
134
+ them out-of-sample before reporting anything.
135
+
136
+ - **Grammar search** (`scan`): enumerates single-pass "scanner" programs until one
137
+ matches the curated examples *and* 60 fuzzed inputs against an independent oracle.
138
+ Kadane, buy-and-sell, and jump-game fall out of examples alone.
139
+ - **Strategy templates** (`vote`, `seen`, `fib`, `circular-kadane`): Boyer-Moore
140
+ voting, hash-set membership, Fibonacci pumping, circular Kadane — all still
141
+ fuzz-verified.
142
+ - **Novelty classification**: `rediscovered` (already in the catalog) vs.
143
+ `new-to-catalog` (a candidate worth porting to the four tiers).
144
+
145
+ Current smoke run: **7 targets · 7 verified · 0 rejected**.
146
+
147
+ ```sh
148
+ uv run python -m synth discover --smoke # ~2 min, CI-friendly
149
+ uv run python -m synth discover # full pass
150
+ uv run python -m synth discover --print # include full report JSON
151
+ ```
152
+
153
+ Output lands in `catalog/discoveries/`: `report.json`, `report.md`, and runnable
154
+ `solutions/*.py`.
155
+
156
+ A discovered jump-game scanner (verified on examples + fuzz):
157
+
158
+ ```python
159
+ def discovered_jump_game(arg):
160
+ s0 = 0
161
+ s1 = 0
162
+ for i, x in enumerate(arg):
163
+ s1 = max(s1, i - s0) # how far the current reach overshoots index i
164
+ s0 = max(s0, i + x) # extend the reach
165
+ return s1 == 0
166
+ ```
167
+
168
+ ## Pattern discovery (original framework)
169
+
170
+ ```python
171
+ from algo_discovery import DiscoveryEngine
172
+
173
+ result = DiscoveryEngine().discover((1, 4, 9, 16, 25))
174
+ print(result.best.name) # "quadratic"
175
+ print(result.best.prediction) # 36
176
+ ```
177
+
178
+ 10 built-in hypotheses (arithmetic, geometric, quadratic, cubic, powers-of-two,
179
+ Fibonacci-like, affine recurrences, prime, alternating-sign, constant) with confidence,
180
+ explanation, and next-term prediction.
181
+
182
+ ```sh
183
+ uv run python -m algo_discovery 1 4 9 16
184
+ ```
185
+
186
+ ## Desktop GUI
187
+
188
+ A small **Tkinter** desktop app (no third-party runtime dependencies) wraps the
189
+ three engines behind a clean dark-themed interface:
190
+
191
+ ```sh
192
+ python -m gui # launch from the repo root
193
+ python engine/runner.py gui # same thing via the dispatcher
194
+ ade-gui # if installed with pip/uv
195
+ ```
196
+
197
+ | Tab | What it does |
198
+ | ----------------- | ---------------------------------------------------------------------- |
199
+ | **Discover** | Run the synthesizer (smoke/full), view the per-target verified table, open the report. |
200
+ | **Pattern discovery** | Enter an integer sequence, discover ranked hypotheses with next-term predictions. |
201
+ | **Engine** | Check vectors, run pytest, build all tiers, benchmark, open docs/GitHub links. |
202
+
203
+ Core logic lives in `gui/core.py` and is tested headlessly in CI (`-p gui` mypy
204
+ + `pytest -q tests/test_gui.py`).
205
+
206
+ ## Container image
207
+
208
+ Prebuilt on **GitHub Packages** (amd64 + arm64) — no install needed:
209
+
210
+ ```sh
211
+ docker pull ghcr.io/dsk-dev-ai/algorithm-discovery-engine:v1.0.0
212
+ docker run --rm ghcr.io/dsk-dev-ai/algorithm-discovery-engine:v1.0.0 --smoke
213
+ ```
214
+
215
+ Tags: `latest`, per-version (`v1.0.0`), and per-commit (`sha-<hash>`). The image runs
216
+ the local algorithm synthesizer by default; override with any `python -m` command.
217
+
218
+ ## Documentation
219
+
220
+ Full docs: **https://dsk-dev-ai.github.io/algorithm-discovery-engine/**
221
+
222
+ Build locally:
223
+
224
+ ```sh
225
+ uv sync --group docs
226
+ uv run mkdocs serve # live preview at http://127.0.0.1:8000
227
+ ```
228
+
229
+ ## Development
230
+
231
+ ```sh
232
+ uv sync --group dev --group docs
233
+ uv run pytest -q # 118+ tests (catalog + synthesizer + GUI core)
234
+ uv run ruff check src tests
235
+ uv run mypy -p algo_discovery -p ads -p synth -p gui
236
+ uv run python -m gui --selftest # headless GUI smoke
237
+ uv run mkdocs build --strict # documentation builds cleanly
238
+ python engine/runner.py check # keep generated vectors in sync before committing
239
+ ```
240
+
241
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the full checklist and how to add a new
242
+ catalog problem or a new discovery target.
243
+
244
+ ## Structure
245
+
246
+ ```
247
+ catalog/problems.json single source of truth (tests + examples)
248
+ catalog/discovery_targets.json discovery targets (curated examples + oracles)
249
+ catalog/discoveries/ synthesizer reports + discovered solutions
250
+ engine/gen_tests.py generates identical test vectors per language
251
+ engine/runner.py build / test / benchmark / synthesize dispatcher
252
+ src/ads/ Python solving engine (regular + advanced)
253
+ src/algo_discovery/ pattern-discovery framework (original)
254
+ src/synth/ local algorithm synthesizer
255
+ src/gui/ Tkinter desktop app (stdlib only)
256
+ docs/ documentation site (MkDocs Material)
257
+ languages/java/src/ads/ Java tier (+ TestRunner, Benchmark)
258
+ languages/cpp/include/ads/ C++17 headers (+ tests, bench)
259
+ languages/rust/src/ Rust tier (+ examples/benchmark.rs)
260
+ ```
261
+
262
+ ## Roadmap
263
+
264
+ - Port `new-to-catalog` discoveries (buy-and-sell, jump game, circular Kadane) into the
265
+ four language tiers as first-class catalog problems.
266
+ - Grow the discovery target corpus (graphs, DP, geometry) and tighten the synthesis
267
+ budget so full passes match CI time.
268
+ - Add GitHub Actions generating the social-preview benchmark delta on every push.
269
+
270
+ ## Sponsor
271
+
272
+ algorithm-discovery-engine is built and maintained by
273
+ [Darshan Kachare](https://github.com/dsk-dev-ai) through
274
+ [NextGenAI Labs](https://github.com/sponsors/dsk-dev-ai).
275
+
276
+ Sponsorship supports development infrastructure, documentation, and long-term
277
+ maintenance of this open-source platform.
278
+
279
+ <a href="https://github.com/sponsors/dsk-dev-ai">
280
+ <img src="https://img.shields.io/badge/%E2%9D%A4%EF%B8%8F-Sponsor_on_GitHub-red?style=for-the-badge&logo=githubsponsors&logoColor=white" alt="Sponsor algorithm-discovery-engine"/>
281
+ </a>
282
+
283
+ ---
284
+
285
+ ## License
286
+
287
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,27 @@
1
+ ads/__init__.py,sha256=Nsr28Xvn69gSxmYmtWrWesQrW8mi3dB1lJbuddatnXQ,1985
2
+ ads/benchmark.py,sha256=34WfmLEymU9i_dvtkBpY6UgU3D1qg1B4zBZfQINh0go,2437
3
+ ads/problems.py,sha256=ndOQjzPdC5A6rVDP-zYZIrc4Y6CVuc2-pac8v9B8FnA,6005
4
+ ads/problems_advanced.py,sha256=z9SEy6OIXcAT3eZg-CSCVYoHC95vz67sjP8K6qNhToE,6615
5
+ ads/structures.py,sha256=3tSjZo1ufZ8IGjShRmuDCDW_p0pUNJv8ZeLl02vgu8s,9782
6
+ ads/structures_advanced.py,sha256=XrhuTL2AGpwDG35BAOoiNjCUqvLcXbJXDia5_zwYki8,11223
7
+ algo_discovery/__init__.py,sha256=0wkXLuFwo-ceK20AOzr2yiBd2xoQ1bYwfPDVFHBeWdI,575
8
+ algo_discovery/__main__.py,sha256=nL83Qb7NliO_tf5LcnEuYFWsDGbjnwfBb_OkqqwRRSA,1112
9
+ algo_discovery/engine.py,sha256=puGgTpiPr3FY1mWOILlqo6jZ7AmsEbvbSFVidq3ddTQ,2062
10
+ algo_discovery/features.py,sha256=eE9artdPffzCPgFnc6bH05I1b4v4aUUGJJxSS2sWOAg,3780
11
+ algo_discovery/hypotheses.py,sha256=Dz4fDb519Glrh6DugkNFvlf6g5noEns_Cf2VwUOlMQU,8686
12
+ algo_discovery/models.py,sha256=qfJXO1jWZLg8mH0KzQWkuS6Ry-DdBhhvGtEF8DztmlI,1720
13
+ gui/__init__.py,sha256=PC5uF1IJSvyzLHV0zIky0OL8_c3Pz7bQiaupvRQq9wM,108
14
+ gui/__main__.py,sha256=rhM-baS6i5YpxD5lwKpJo3yjUH3fK3eVFLkSry38FH4,603
15
+ gui/app.py,sha256=CcG_U9qRbZTRQLpqT917n5rOD6QqtvFKc-0m9JeNJvg,15066
16
+ gui/core.py,sha256=XZkPIP5-pYLiTXs1CT1kI_ZYhjefQQ5uZe80oHg7Dn8,4962
17
+ synth/__init__.py,sha256=kURnZrnKktKr-YRkqmNVER36E8cn2Z9f4_rqqMCLMGI,720
18
+ synth/__main__.py,sha256=mq6aMOLoL2i7nOEhQWGRtmVciSn6ftwjcX-fZgUnpb8,1950
19
+ synth/corpus.py,sha256=ew9FfxEBB_L5I2vtC_BLwxwusiRMaQgdvR5OtEUUWQM,6832
20
+ synth/discovery.py,sha256=qCGyKOxmJR_8JqFKLVOG8iBxkcziQH-7km6cIxt6Okg,7107
21
+ synth/grammar.py,sha256=3brCBakaYkTA_78tmnuO7IVaBlE97K5f7RHABepnb0c,5107
22
+ synth/search.py,sha256=OWY7lCVmd68RVyWFaMdBth3tDsd1gRtgoByBCj_rHcw,14324
23
+ algorithm_discovery_engine-1.0.0.dist-info/METADATA,sha256=NpKKs8jAWz_-tMfc0cYnjqFNMiDYNgXil77H65ePVT4,13268
24
+ algorithm_discovery_engine-1.0.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
25
+ algorithm_discovery_engine-1.0.0.dist-info/entry_points.txt,sha256=9Xu5qHUd2jvpS5KzjBQsJjGkO4i3vZoDkP1oKE_6KSA,41
26
+ algorithm_discovery_engine-1.0.0.dist-info/licenses/LICENSE,sha256=xrR2ODTGVvR75aaH4il5G4R8JWLKGPYN8jiqCKCvc74,1072
27
+ algorithm_discovery_engine-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ade-gui = gui.app:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Darshan Kachare
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
gui/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """Desktop GUI shell for algorithm-discovery-engine (stdlib Tkinter)."""
2
+
3
+ from gui import core # noqa: F401