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.
- ads/__init__.py +85 -0
- ads/benchmark.py +84 -0
- ads/problems.py +190 -0
- ads/problems_advanced.py +203 -0
- ads/structures.py +370 -0
- ads/structures_advanced.py +385 -0
- algo_discovery/__init__.py +19 -0
- algo_discovery/__main__.py +38 -0
- algo_discovery/engine.py +64 -0
- algo_discovery/features.py +115 -0
- algo_discovery/hypotheses.py +251 -0
- algo_discovery/models.py +63 -0
- algorithm_discovery_engine-1.0.0.dist-info/METADATA +287 -0
- algorithm_discovery_engine-1.0.0.dist-info/RECORD +27 -0
- algorithm_discovery_engine-1.0.0.dist-info/WHEEL +4 -0
- algorithm_discovery_engine-1.0.0.dist-info/entry_points.txt +2 -0
- algorithm_discovery_engine-1.0.0.dist-info/licenses/LICENSE +21 -0
- gui/__init__.py +3 -0
- gui/__main__.py +26 -0
- gui/app.py +407 -0
- gui/core.py +149 -0
- synth/__init__.py +22 -0
- synth/__main__.py +66 -0
- synth/corpus.py +222 -0
- synth/discovery.py +198 -0
- synth/grammar.py +174 -0
- synth/search.py +432 -0
ads/structures.py
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
"""Regular Python data-structure tier: simple, readable implementations.
|
|
2
|
+
|
|
3
|
+
Mirror the Java / C++ / Rust ports. Each structure exposes the operation
|
|
4
|
+
contracts listed in ``catalog/problems.json``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from collections import deque as _deque
|
|
10
|
+
|
|
11
|
+
_SENTINEL = -1
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Stack:
|
|
15
|
+
"""LIFO stack backed by a list."""
|
|
16
|
+
|
|
17
|
+
__slots__ = ("_items",)
|
|
18
|
+
|
|
19
|
+
def __init__(self) -> None:
|
|
20
|
+
self._items: list[int] = []
|
|
21
|
+
|
|
22
|
+
def push(self, value: int) -> None:
|
|
23
|
+
self._items.append(value)
|
|
24
|
+
|
|
25
|
+
def pop(self) -> int:
|
|
26
|
+
return self._items.pop() if self._items else _SENTINEL
|
|
27
|
+
|
|
28
|
+
def peek(self) -> int:
|
|
29
|
+
return self._items[-1] if self._items else _SENTINEL
|
|
30
|
+
|
|
31
|
+
def is_empty(self) -> bool:
|
|
32
|
+
return not self._items
|
|
33
|
+
|
|
34
|
+
def size(self) -> int:
|
|
35
|
+
return len(self._items)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Queue:
|
|
39
|
+
"""FIFO queue backed by a deque."""
|
|
40
|
+
|
|
41
|
+
__slots__ = ("_items",)
|
|
42
|
+
|
|
43
|
+
def __init__(self) -> None:
|
|
44
|
+
self._items: _deque[int] = _deque()
|
|
45
|
+
|
|
46
|
+
def enqueue(self, value: int) -> None:
|
|
47
|
+
self._items.append(value)
|
|
48
|
+
|
|
49
|
+
def dequeue(self) -> int:
|
|
50
|
+
return self._items.popleft() if self._items else _SENTINEL
|
|
51
|
+
|
|
52
|
+
def peek(self) -> int:
|
|
53
|
+
return self._items[0] if self._items else _SENTINEL
|
|
54
|
+
|
|
55
|
+
def is_empty(self) -> bool:
|
|
56
|
+
return not self._items
|
|
57
|
+
|
|
58
|
+
def size(self) -> int:
|
|
59
|
+
return len(self._items)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class _Node:
|
|
63
|
+
__slots__ = ("next", "value")
|
|
64
|
+
|
|
65
|
+
def __init__(self, value: int) -> None:
|
|
66
|
+
self.value = value
|
|
67
|
+
self.next: _Node | None = None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class LinkedList:
|
|
71
|
+
"""Singly linked list."""
|
|
72
|
+
|
|
73
|
+
__slots__ = ("_head", "_size", "_tail")
|
|
74
|
+
|
|
75
|
+
def __init__(self) -> None:
|
|
76
|
+
self._head: _Node | None = None
|
|
77
|
+
self._tail: _Node | None = None
|
|
78
|
+
self._size = 0
|
|
79
|
+
|
|
80
|
+
def append(self, value: int) -> None:
|
|
81
|
+
node = _Node(value)
|
|
82
|
+
if self._tail is None:
|
|
83
|
+
self._head = self._tail = node
|
|
84
|
+
else:
|
|
85
|
+
self._tail.next = node
|
|
86
|
+
self._tail = node
|
|
87
|
+
self._size += 1
|
|
88
|
+
|
|
89
|
+
def prepend(self, value: int) -> None:
|
|
90
|
+
node = _Node(value)
|
|
91
|
+
node.next = self._head
|
|
92
|
+
self._head = node
|
|
93
|
+
if self._tail is None:
|
|
94
|
+
self._tail = node
|
|
95
|
+
self._size += 1
|
|
96
|
+
|
|
97
|
+
def get(self, index: int) -> int:
|
|
98
|
+
if index < 0 or index >= self._size:
|
|
99
|
+
return _SENTINEL
|
|
100
|
+
node = self._head
|
|
101
|
+
for _ in range(index):
|
|
102
|
+
node = node.next # type: ignore[union-attr]
|
|
103
|
+
return node.value # type: ignore[union-attr]
|
|
104
|
+
|
|
105
|
+
def contains(self, value: int) -> bool:
|
|
106
|
+
node = self._head
|
|
107
|
+
while node is not None:
|
|
108
|
+
if node.value == value:
|
|
109
|
+
return True
|
|
110
|
+
node = node.next
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
def remove(self, value: int) -> bool:
|
|
114
|
+
node, previous = self._head, None
|
|
115
|
+
while node is not None:
|
|
116
|
+
if node.value == value:
|
|
117
|
+
if previous is None:
|
|
118
|
+
self._head = node.next
|
|
119
|
+
else:
|
|
120
|
+
previous.next = node.next
|
|
121
|
+
if node is self._tail:
|
|
122
|
+
self._tail = previous
|
|
123
|
+
self._size -= 1
|
|
124
|
+
return True
|
|
125
|
+
previous, node = node, node.next
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
def size(self) -> int:
|
|
129
|
+
return self._size
|
|
130
|
+
|
|
131
|
+
def to_list(self) -> list[int]:
|
|
132
|
+
out: list[int] = []
|
|
133
|
+
node = self._head
|
|
134
|
+
while node is not None:
|
|
135
|
+
out.append(node.value)
|
|
136
|
+
node = node.next
|
|
137
|
+
return out
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class BST:
|
|
141
|
+
"""Binary search tree."""
|
|
142
|
+
|
|
143
|
+
__slots__ = ("_root", "_size")
|
|
144
|
+
|
|
145
|
+
def __init__(self) -> None:
|
|
146
|
+
self._root: _BSTNode | None = None
|
|
147
|
+
self._size = 0
|
|
148
|
+
|
|
149
|
+
def insert(self, value: int) -> None:
|
|
150
|
+
if self._root is None:
|
|
151
|
+
self._root = _BSTNode(value)
|
|
152
|
+
self._size = 1
|
|
153
|
+
return
|
|
154
|
+
node = self._root
|
|
155
|
+
while True:
|
|
156
|
+
if value < node.value:
|
|
157
|
+
if node.left is None:
|
|
158
|
+
node.left = _BSTNode(value)
|
|
159
|
+
break
|
|
160
|
+
node = node.left
|
|
161
|
+
elif value > node.value:
|
|
162
|
+
if node.right is None:
|
|
163
|
+
node.right = _BSTNode(value)
|
|
164
|
+
break
|
|
165
|
+
node = node.right
|
|
166
|
+
else:
|
|
167
|
+
return
|
|
168
|
+
self._size += 1
|
|
169
|
+
|
|
170
|
+
def contains(self, value: int) -> bool:
|
|
171
|
+
node = self._root
|
|
172
|
+
while node is not None:
|
|
173
|
+
if value == node.value:
|
|
174
|
+
return True
|
|
175
|
+
node = node.left if value < node.value else node.right
|
|
176
|
+
return False
|
|
177
|
+
|
|
178
|
+
def min(self) -> int:
|
|
179
|
+
node = self._root
|
|
180
|
+
if node is None:
|
|
181
|
+
return _SENTINEL
|
|
182
|
+
while node.left is not None:
|
|
183
|
+
node = node.left
|
|
184
|
+
return node.value
|
|
185
|
+
|
|
186
|
+
def max(self) -> int:
|
|
187
|
+
node = self._root
|
|
188
|
+
if node is None:
|
|
189
|
+
return _SENTINEL
|
|
190
|
+
while node.right is not None:
|
|
191
|
+
node = node.right
|
|
192
|
+
return node.value
|
|
193
|
+
|
|
194
|
+
def height(self) -> int:
|
|
195
|
+
return _height(self._root)
|
|
196
|
+
|
|
197
|
+
def size(self) -> int:
|
|
198
|
+
return self._size
|
|
199
|
+
|
|
200
|
+
def in_order(self) -> list[int]:
|
|
201
|
+
out: list[int] = []
|
|
202
|
+
_in_order(self._root, out)
|
|
203
|
+
return out
|
|
204
|
+
|
|
205
|
+
def remove(self, value: int) -> bool:
|
|
206
|
+
found = self._contains(self._root, value)
|
|
207
|
+
if not found:
|
|
208
|
+
return False
|
|
209
|
+
self._root = _remove(self._root, value)
|
|
210
|
+
self._size -= 1
|
|
211
|
+
return True
|
|
212
|
+
|
|
213
|
+
@staticmethod
|
|
214
|
+
def _contains(node: _BSTNode | None, value: int) -> bool:
|
|
215
|
+
if node is None:
|
|
216
|
+
return False
|
|
217
|
+
if value == node.value:
|
|
218
|
+
return True
|
|
219
|
+
return BST._contains(node.left if value < node.value else node.right, value)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class _BSTNode:
|
|
223
|
+
__slots__ = ("left", "right", "value")
|
|
224
|
+
|
|
225
|
+
def __init__(self, value: int) -> None:
|
|
226
|
+
self.value = value
|
|
227
|
+
self.left: _BSTNode | None = None
|
|
228
|
+
self.right: _BSTNode | None = None
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def _height(node: _BSTNode | None) -> int:
|
|
232
|
+
if node is None:
|
|
233
|
+
return -1
|
|
234
|
+
return 1 + max(_height(node.left), _height(node.right))
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _in_order(node: _BSTNode | None, out: list[int]) -> None:
|
|
238
|
+
if node is None:
|
|
239
|
+
return
|
|
240
|
+
_in_order(node.left, out)
|
|
241
|
+
out.append(node.value)
|
|
242
|
+
_in_order(node.right, out)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def _remove(node: _BSTNode | None, value: int) -> _BSTNode | None:
|
|
246
|
+
if node is None:
|
|
247
|
+
return None
|
|
248
|
+
if value < node.value:
|
|
249
|
+
node.left = _remove(node.left, value)
|
|
250
|
+
elif value > node.value:
|
|
251
|
+
node.right = _remove(node.right, value)
|
|
252
|
+
else:
|
|
253
|
+
if node.left is None:
|
|
254
|
+
return node.right
|
|
255
|
+
if node.right is None:
|
|
256
|
+
return node.left
|
|
257
|
+
successor = node.right
|
|
258
|
+
while successor.left is not None:
|
|
259
|
+
successor = successor.left
|
|
260
|
+
node.value = successor.value
|
|
261
|
+
node.right = _remove(node.right, successor.value)
|
|
262
|
+
return node
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
class Trie:
|
|
266
|
+
"""Prefix trie storing unique words."""
|
|
267
|
+
|
|
268
|
+
__slots__ = ("_root", "_size")
|
|
269
|
+
|
|
270
|
+
def __init__(self) -> None:
|
|
271
|
+
self._root: _TrieNode = _TrieNode()
|
|
272
|
+
self._size = 0
|
|
273
|
+
|
|
274
|
+
def insert(self, word: str) -> None:
|
|
275
|
+
node = self._root
|
|
276
|
+
for ch in word:
|
|
277
|
+
if ch not in node.children:
|
|
278
|
+
node.children[ch] = _TrieNode()
|
|
279
|
+
node = node.children[ch]
|
|
280
|
+
if not node.terminal:
|
|
281
|
+
node.terminal = True
|
|
282
|
+
self._size += 1
|
|
283
|
+
|
|
284
|
+
def search(self, word: str) -> bool:
|
|
285
|
+
node = self._root
|
|
286
|
+
for ch in word:
|
|
287
|
+
if ch not in node.children:
|
|
288
|
+
return False
|
|
289
|
+
node = node.children[ch]
|
|
290
|
+
return node.terminal
|
|
291
|
+
|
|
292
|
+
def starts_with(self, prefix: str) -> bool:
|
|
293
|
+
node = self._root
|
|
294
|
+
for ch in prefix:
|
|
295
|
+
if ch not in node.children:
|
|
296
|
+
return False
|
|
297
|
+
node = node.children[ch]
|
|
298
|
+
return True
|
|
299
|
+
|
|
300
|
+
def size(self) -> int:
|
|
301
|
+
return self._size
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class _TrieNode:
|
|
305
|
+
__slots__ = ("children", "terminal")
|
|
306
|
+
|
|
307
|
+
def __init__(self) -> None:
|
|
308
|
+
self.children: dict[str, _TrieNode] = {}
|
|
309
|
+
self.terminal = False
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class MinHeap:
|
|
313
|
+
"""Binary min-heap over a list."""
|
|
314
|
+
|
|
315
|
+
__slots__ = ("_items",)
|
|
316
|
+
|
|
317
|
+
def __init__(self) -> None:
|
|
318
|
+
self._items: list[int] = []
|
|
319
|
+
|
|
320
|
+
def push(self, value: int) -> None:
|
|
321
|
+
self._items.append(value)
|
|
322
|
+
self._sift_up(len(self._items) - 1)
|
|
323
|
+
|
|
324
|
+
def pop(self) -> int:
|
|
325
|
+
if not self._items:
|
|
326
|
+
return _SENTINEL
|
|
327
|
+
top = self._items[0]
|
|
328
|
+
last = self._items.pop()
|
|
329
|
+
if self._items:
|
|
330
|
+
self._items[0] = last
|
|
331
|
+
self._sift_down(0)
|
|
332
|
+
return top
|
|
333
|
+
|
|
334
|
+
def peek(self) -> int:
|
|
335
|
+
return self._items[0] if self._items else _SENTINEL
|
|
336
|
+
|
|
337
|
+
def is_empty(self) -> bool:
|
|
338
|
+
return not self._items
|
|
339
|
+
|
|
340
|
+
def size(self) -> int:
|
|
341
|
+
return len(self._items)
|
|
342
|
+
|
|
343
|
+
def _sift_up(self, index: int) -> None:
|
|
344
|
+
while index > 0:
|
|
345
|
+
parent = (index - 1) // 2
|
|
346
|
+
if self._items[parent] <= self._items[index]:
|
|
347
|
+
return
|
|
348
|
+
self._items[parent], self._items[index] = (
|
|
349
|
+
self._items[index],
|
|
350
|
+
self._items[parent],
|
|
351
|
+
)
|
|
352
|
+
index = parent
|
|
353
|
+
|
|
354
|
+
def _sift_down(self, index: int) -> None:
|
|
355
|
+
size = len(self._items)
|
|
356
|
+
while True:
|
|
357
|
+
left = 2 * index + 1
|
|
358
|
+
right = left + 1
|
|
359
|
+
smallest = index
|
|
360
|
+
if left < size and self._items[left] < self._items[smallest]:
|
|
361
|
+
smallest = left
|
|
362
|
+
if right < size and self._items[right] < self._items[smallest]:
|
|
363
|
+
smallest = right
|
|
364
|
+
if smallest == index:
|
|
365
|
+
return
|
|
366
|
+
self._items[index], self._items[smallest] = (
|
|
367
|
+
self._items[smallest],
|
|
368
|
+
self._items[index],
|
|
369
|
+
)
|
|
370
|
+
index = smallest
|