mathai 2.4.7__tar.gz → 2.4.8__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.
- {mathai-2.4.7 → mathai-2.4.8}/PKG-INFO +1 -1
- {mathai-2.4.7 → mathai-2.4.8}/mathai/__init__.py +0 -2
- {mathai-2.4.7 → mathai-2.4.8}/mathai/benchmark.py +12 -129
- {mathai-2.4.7 → mathai-2.4.8}/mathai/decision.py +9 -7
- {mathai-2.4.7 → mathai-2.4.8}/mathai.egg-info/PKG-INFO +1 -1
- {mathai-2.4.7 → mathai-2.4.8}/setup.py +1 -1
- {mathai-2.4.7 → mathai-2.4.8}/README.md +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/apart.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/base.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/diff.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/electronic.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/expand.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/factor.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/formula_applier.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/formula_compiler.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/fraction.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/graphics.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/integrate.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/inverse.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/lambda_calculus.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/limit.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/linear.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/logic.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/matrix.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/ml.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/mlscalar.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/ncert_data.txt +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/ode.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/parser.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/pde.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/printeq.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/qm.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/simplify.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/statistics.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/test.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/tool.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/trig.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai/univariate_inequality.py +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai.egg-info/SOURCES.txt +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai.egg-info/dependency_links.txt +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/mathai.egg-info/top_level.txt +0 -0
- {mathai-2.4.7 → mathai-2.4.8}/setup.cfg +0 -0
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import atexit
|
|
2
1
|
import copy
|
|
3
|
-
import multiprocessing
|
|
4
2
|
from pathlib import Path
|
|
5
3
|
|
|
6
4
|
from .simplify import simplify
|
|
@@ -175,138 +173,23 @@ def print_tree(node, depth=0):
|
|
|
175
173
|
|
|
176
174
|
|
|
177
175
|
# ---------------------------------------------------------------------------
|
|
178
|
-
#
|
|
179
|
-
#
|
|
180
|
-
# Design: nothing heavy is pickled per call.
|
|
181
|
-
# - Each worker builds the tree once, from the dataset name, at pool start.
|
|
182
|
-
# - Terminal conditions are looked up by name in TERMINAL_CONDITIONS, so no
|
|
183
|
-
# function object is ever sent to a worker.
|
|
184
|
-
# - Pools persist across calls, so spawn/import cost is paid once.
|
|
185
|
-
# - Per task, only (branch index, equation, condition name, generation)
|
|
186
|
-
# is sent.
|
|
176
|
+
# Serial Execution Entry Point
|
|
187
177
|
# ---------------------------------------------------------------------------
|
|
188
178
|
|
|
189
|
-
# Register terminal conditions here. Workers re-import this module and find
|
|
190
|
-
# them by name.
|
|
191
|
-
TERMINAL_CONDITIONS = {
|
|
192
|
-
"no_integrate": lambda eq: not contain2(eq, "f_integrate"),
|
|
193
|
-
}
|
|
194
179
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
def _get_tree(data_name):
|
|
204
|
-
if data_name not in _TREES:
|
|
205
|
-
_TREES[data_name] = strategy_tree(load_sequences(data_name))
|
|
206
|
-
return _TREES[data_name]
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
def _init_worker(data_name, gen):
|
|
210
|
-
global _W_BRANCHES, _W_GEN
|
|
211
|
-
_W_BRANCHES = list(_get_tree(data_name).children.values())
|
|
212
|
-
_W_GEN = gen
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
def _worker(task):
|
|
216
|
-
idx, equation, cond_name, my_gen = task
|
|
217
|
-
|
|
218
|
-
# Stale task left over from a call that already finished: skip it.
|
|
219
|
-
if _W_GEN.value != my_gen:
|
|
220
|
-
return []
|
|
221
|
-
|
|
222
|
-
cond = TERMINAL_CONDITIONS[cond_name] if cond_name else None
|
|
223
|
-
try:
|
|
224
|
-
return _W_BRANCHES[idx].execute(equation, [], cond)
|
|
225
|
-
except Exception:
|
|
226
|
-
# A failing branch must not discard results from other branches.
|
|
227
|
-
return []
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
def _first_match(results, cond):
|
|
231
|
-
for eq, seq in results:
|
|
232
|
-
if cond is None or cond(eq):
|
|
233
|
-
return [(eq, seq)]
|
|
234
|
-
return None
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
def _execute_sequential(data_name, equation, cond_name):
|
|
238
|
-
cond = TERMINAL_CONDITIONS[cond_name] if cond_name else None
|
|
239
|
-
|
|
240
|
-
for child in _get_tree(data_name).children.values():
|
|
180
|
+
def execute_serial(tree, equation, terminal_condition=None):
|
|
181
|
+
"""
|
|
182
|
+
Executes the strategy tree serially and returns at most one
|
|
183
|
+
matching path as a list of tuples: [(equation, sequence)].
|
|
184
|
+
"""
|
|
185
|
+
for child in tree.children.values():
|
|
241
186
|
try:
|
|
242
|
-
results = child.execute(copy.deepcopy(equation), [],
|
|
187
|
+
results = child.execute(copy.deepcopy(equation), [], terminal_condition)
|
|
243
188
|
except Exception:
|
|
244
|
-
continue
|
|
189
|
+
continue
|
|
245
190
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
191
|
+
for eq, seq in results:
|
|
192
|
+
if terminal_condition is None or terminal_condition(eq):
|
|
193
|
+
return [(eq, seq)]
|
|
249
194
|
|
|
250
195
|
return []
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
def _get_pool(data_name, n_cores):
|
|
254
|
-
key = (data_name, n_cores)
|
|
255
|
-
|
|
256
|
-
if key not in _POOLS:
|
|
257
|
-
gen = multiprocessing.Value("i", 0, lock=False)
|
|
258
|
-
pool = multiprocessing.Pool(
|
|
259
|
-
n_cores, initializer=_init_worker, initargs=(data_name, gen)
|
|
260
|
-
)
|
|
261
|
-
_POOLS[key] = (pool, gen)
|
|
262
|
-
|
|
263
|
-
return _POOLS[key]
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
def shutdown_pools():
|
|
267
|
-
for pool, _ in _POOLS.values():
|
|
268
|
-
pool.terminate()
|
|
269
|
-
pool.join()
|
|
270
|
-
_POOLS.clear()
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
atexit.register(shutdown_pools)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
def execute_parallel(data_name, equation, n_cores=None, condition_name=None):
|
|
277
|
-
"""
|
|
278
|
-
Run the strategy tree for `data_name` against `equation` and return at
|
|
279
|
-
most one result as a one-item list [(equation, sequence)].
|
|
280
|
-
|
|
281
|
-
condition_name: key into TERMINAL_CONDITIONS, or None.
|
|
282
|
-
|
|
283
|
-
On Windows/macOS (spawn start method) callers using n_cores > 1 must be
|
|
284
|
-
guarded by ``if __name__ == "__main__":``.
|
|
285
|
-
"""
|
|
286
|
-
n_branches = len(_get_tree(data_name).children)
|
|
287
|
-
if n_branches == 0:
|
|
288
|
-
return []
|
|
289
|
-
|
|
290
|
-
if n_cores is None:
|
|
291
|
-
n_cores = multiprocessing.cpu_count()
|
|
292
|
-
# Never more processes than branches, never fewer than one
|
|
293
|
-
n_cores = max(1, min(n_cores, n_branches))
|
|
294
|
-
|
|
295
|
-
if n_cores == 1:
|
|
296
|
-
return _execute_sequential(data_name, equation, condition_name)
|
|
297
|
-
|
|
298
|
-
cond = TERMINAL_CONDITIONS[condition_name] if condition_name else None
|
|
299
|
-
pool, gen = _get_pool(data_name, n_cores)
|
|
300
|
-
|
|
301
|
-
my_gen = gen.value + 1
|
|
302
|
-
gen.value = my_gen
|
|
303
|
-
tasks = [(i, equation, condition_name, my_gen) for i in range(n_branches)]
|
|
304
|
-
|
|
305
|
-
try:
|
|
306
|
-
for branch_results in pool.imap_unordered(_worker, tasks):
|
|
307
|
-
match = _first_match(branch_results, cond)
|
|
308
|
-
if match is not None:
|
|
309
|
-
return match
|
|
310
|
-
return []
|
|
311
|
-
finally:
|
|
312
|
-
gen.value = my_gen + 1 # cancels any still-queued tasks
|
|
@@ -15,7 +15,7 @@ from .factor import factor2, factor
|
|
|
15
15
|
from .limit import limit1, limit5
|
|
16
16
|
from .linear import linear_solve
|
|
17
17
|
from .matrix import matrix_solve, matrix_formula
|
|
18
|
-
from .benchmark import load_sequences, strategy_tree,
|
|
18
|
+
from .benchmark import load_sequences, strategy_tree, execute_serial
|
|
19
19
|
|
|
20
20
|
def vlist_2(eq):
|
|
21
21
|
out = []
|
|
@@ -61,19 +61,21 @@ def solve_subs(q):
|
|
|
61
61
|
if len(solution.keys()) == 0:
|
|
62
62
|
return orig
|
|
63
63
|
return operation("f_and", [item for item in lst if all(not contain(item, tree_form(key)) for key in solution.keys())] + [TreeNode("f_eq", [tree_form(key), item]) for key, item in solution.items()])
|
|
64
|
+
def _no_integrate_left(eq):
|
|
65
|
+
return eq.name == "f_range" or eq.name == "s_true" or all(not contain2(eq, "f_"+item) for item in "eq integrate subs limit limitpinf limitninf".split(" "))
|
|
64
66
|
|
|
65
67
|
|
|
66
|
-
def god2(string
|
|
67
|
-
out =
|
|
68
|
-
"ncert_data"
|
|
68
|
+
def god2(string):
|
|
69
|
+
out = execute_serial(
|
|
70
|
+
strategy_tree(load_sequences("ncert_data")),
|
|
71
|
+
simplify(parse(string)),
|
|
72
|
+
_no_integrate_left,
|
|
69
73
|
)
|
|
70
|
-
|
|
71
74
|
if len(out) >= 1:
|
|
72
75
|
print(string)
|
|
73
76
|
print("=>", out[0][0])
|
|
74
77
|
print(["parse", "simplify"] + out[0][1])
|
|
75
|
-
|
|
76
|
-
return out
|
|
78
|
+
return None
|
|
77
79
|
|
|
78
80
|
def god(string, debug=True):
|
|
79
81
|
if debug:
|
|
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
|
|
|
3
3
|
|
|
4
4
|
setup(
|
|
5
5
|
name="mathai",
|
|
6
|
-
version="2.4.
|
|
6
|
+
version="2.4.8",
|
|
7
7
|
description="Mathematics solving Ai tailored to NCERT",
|
|
8
8
|
long_description=Path("README.md").read_text(encoding="utf-8"),
|
|
9
9
|
long_description_content_type="text/markdown",
|
|
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
|
|
File without changes
|