mathjson-solver 1.16.1__tar.gz → 1.18.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.
- {mathjson_solver-1.16.1/src/mathjson_solver.egg-info → mathjson_solver-1.18.0}/PKG-INFO +21 -9
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/README.md +20 -7
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/setup.cfg +2 -2
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/setup.py +2 -2
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/src/mathjson_solver/__main__.py +153 -14
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0/src/mathjson_solver.egg-info}/PKG-INFO +21 -9
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/src/mathjson_solver.egg-info/SOURCES.txt +5 -2
- mathjson_solver-1.16.1/tests/test_CumulativeProduct.py → mathjson_solver-1.18.0/tests/test_cumulative.py +11 -0
- mathjson_solver-1.18.0/tests/test_datetime.py +219 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_equal.py +5 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_gail_model.py +1 -1
- mathjson_solver-1.18.0/tests/test_reduce_simple.py +209 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_simple_cases.py +6 -0
- mathjson_solver-1.18.0/tests/test_state_tuples_reduce.py +180 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_with_pytest.py +10 -72
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/LICENSE +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/pyproject.toml +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/src/mathjson_solver/__init__.py +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/src/mathjson_solver.egg-info/dependency_links.txt +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/src/mathjson_solver.egg-info/top_level.txt +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_TrapezoidalIntegratel.py +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_atindex.py +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_exceptions.py +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_extract_variables.py +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_findinterval.py +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_interpolate.py +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_range.py +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_scalars.py +0 -0
- {mathjson_solver-1.16.1 → mathjson_solver-1.18.0}/tests/test_sets.py +0 -0
- /mathjson_solver-1.16.1/tests/test_Slice.py → /mathjson_solver-1.18.0/tests/test_slice.py +0 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mathjson-solver
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.18.0
|
|
4
4
|
Summary: Utilities for MathJSON evaluation
|
|
5
5
|
Home-page: https://github.com/LongenesisLtd/mathjson-solver
|
|
6
6
|
Author: Martins Mednis
|
|
7
7
|
Author-email: mrt@mednis.info
|
|
8
8
|
Project-URL: Bug Tracker, https://github.com/LongenesisLtd/mathjson-solver/issues
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
10
|
Classifier: Operating System :: OS Independent
|
|
12
11
|
Requires-Python: >=3.6
|
|
13
12
|
Description-Content-Type: text/markdown
|
|
@@ -33,8 +32,6 @@ A reliable Python library for numerically evaluating mathematical expressions in
|
|
|
33
32
|
|
|
34
33
|
**What is MathJSON?** MathJSON represents mathematical expressions as JSON arrays, like `["Add", 1, 2, 3]` for 1+2+3. This format is safe, structured, and easy to generate programmatically.
|
|
35
34
|
|
|
36
|
-
Inspired by [CortexJS Compute Engine](https://cortexjs.io/compute-engine/) though designed as an independent implementation focused on our specific use cases.
|
|
37
|
-
|
|
38
35
|
## Table of Contents
|
|
39
36
|
- [Installation](#installation)
|
|
40
37
|
- [Quick Start](#quick-start)
|
|
@@ -80,21 +77,32 @@ except MathJSONException as e:
|
|
|
80
77
|
# Math error: Problem in Divide. ['Divide', 1, 0]. division by zero
|
|
81
78
|
```
|
|
82
79
|
|
|
80
|
+
**Think Functional:** MathJSON Solver embraces functional programming principles. Instead of writing loops and modifying variables, you compose expressions that transform data. Functions like `Map`, `Reduce`, and `Filter` let you process arrays elegantly, while immutable operations ensure predictable, side-effect-free calculations. Don't worry if you're new to functional programming — the examples will guide you naturally into this powerful paradigm.
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
# Functional approach: transform data with expressions
|
|
84
|
+
solver(["Map", ["Array", 1, 2, 3, 4], ["Multiply"], 2]) # [2, 4, 6, 8]
|
|
85
|
+
solver(["Reduce", ["Array", 1, 2, 3, 4], 0, ["Add", "acc", "item"],
|
|
86
|
+
["Variable", "acc"], ["Variable", "item"], ["Variable", "i"]]) # 10
|
|
87
|
+
```
|
|
88
|
+
|
|
83
89
|
## Supported Operations
|
|
84
90
|
|
|
85
91
|
The library supports a comprehensive set of mathematical operations:
|
|
86
92
|
|
|
87
|
-
* **Arithmetic:** Add, Sum, Subtract, Multiply, Divide, Negate, Power, Square, Root, Sqrt, Abs, Round
|
|
93
|
+
* **Arithmetic:** Add, Sum, Subtract, Multiply, Divide, Negate, Power, Square, Root, Sqrt, Abs, Round, Floor, Ceil
|
|
88
94
|
* **Trigonometry:** Sin, Cos, Tan, Arcsin, Arccos, Arctan
|
|
89
95
|
* **Logarithms:** Log, Log2, Log10, Exp
|
|
90
96
|
* **Comparison:** Equal, StrictEqual, NotEqual, Greater, GreaterEqual, Less, LessEqual
|
|
91
|
-
* **Logic & Sets:** Any, All, Not, In, NotIn, ContainsAnyOf, ContainsAllOf, ContainsNoneOf
|
|
97
|
+
* **Logic & Sets:** Any, All, Not, And, Or, In, NotIn, ContainsAnyOf, ContainsAllOf, ContainsNoneOf
|
|
92
98
|
* **Statistics:** Average, Max, Min, Median, Length
|
|
93
|
-
* **
|
|
99
|
+
* **Functional Programming:** Map, Reduce, Filter
|
|
100
|
+
* **Arrays:** Array creation, GenerateRange, AtIndex, Slice, Appended, CumulativeSum, CumulativeProduct
|
|
94
101
|
* **Control Flow:** If statements, Switch-Case, Constants definition
|
|
95
102
|
* **Type Conversion:** Int, Float, Str, IsDefined
|
|
96
|
-
* **Date/Time:** Strptime, Strftime, Today, Now, TimeDelta functions
|
|
97
|
-
* **
|
|
103
|
+
* **Date/Time:** Strptime, Strftime, Today, Now, TimeDelta functions (Weeks, Days, Hours, Minutes)
|
|
104
|
+
* **Integration:** TrapezoidalIntegrate (requires numpy), Interp, FindIntervalIndex, Variable references
|
|
105
|
+
* **Advanced:** HasMatchingSublist for pattern matching
|
|
98
106
|
* **Constants:** Pi
|
|
99
107
|
|
|
100
108
|
[View complete documentation with examples →](https://github.com/LongenesisLtd/mathjson-solver/blob/main/docs/README.md)
|
|
@@ -161,6 +169,10 @@ We welcome contributions! Please feel free to:
|
|
|
161
169
|
|
|
162
170
|
[View license information](https://github.com/LongenesisLtd/mathjson-solver/blob/main/LICENSE)
|
|
163
171
|
|
|
172
|
+
## References
|
|
173
|
+
|
|
174
|
+
This implementation was inspired by the [CortexJS Compute Engine](https://cortexjs.io/compute-engine/), though designed as an independent implementation focused on our specific use cases.
|
|
175
|
+
|
|
164
176
|
---
|
|
165
177
|
|
|
166
178
|
Made with ❤️ by [Longenesis](https://longenesis.com/team)
|
|
@@ -8,8 +8,6 @@ A reliable Python library for numerically evaluating mathematical expressions in
|
|
|
8
8
|
|
|
9
9
|
**What is MathJSON?** MathJSON represents mathematical expressions as JSON arrays, like `["Add", 1, 2, 3]` for 1+2+3. This format is safe, structured, and easy to generate programmatically.
|
|
10
10
|
|
|
11
|
-
Inspired by [CortexJS Compute Engine](https://cortexjs.io/compute-engine/) though designed as an independent implementation focused on our specific use cases.
|
|
12
|
-
|
|
13
11
|
## Table of Contents
|
|
14
12
|
- [Installation](#installation)
|
|
15
13
|
- [Quick Start](#quick-start)
|
|
@@ -55,21 +53,32 @@ except MathJSONException as e:
|
|
|
55
53
|
# Math error: Problem in Divide. ['Divide', 1, 0]. division by zero
|
|
56
54
|
```
|
|
57
55
|
|
|
56
|
+
**Think Functional:** MathJSON Solver embraces functional programming principles. Instead of writing loops and modifying variables, you compose expressions that transform data. Functions like `Map`, `Reduce`, and `Filter` let you process arrays elegantly, while immutable operations ensure predictable, side-effect-free calculations. Don't worry if you're new to functional programming — the examples will guide you naturally into this powerful paradigm.
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
# Functional approach: transform data with expressions
|
|
60
|
+
solver(["Map", ["Array", 1, 2, 3, 4], ["Multiply"], 2]) # [2, 4, 6, 8]
|
|
61
|
+
solver(["Reduce", ["Array", 1, 2, 3, 4], 0, ["Add", "acc", "item"],
|
|
62
|
+
["Variable", "acc"], ["Variable", "item"], ["Variable", "i"]]) # 10
|
|
63
|
+
```
|
|
64
|
+
|
|
58
65
|
## Supported Operations
|
|
59
66
|
|
|
60
67
|
The library supports a comprehensive set of mathematical operations:
|
|
61
68
|
|
|
62
|
-
* **Arithmetic:** Add, Sum, Subtract, Multiply, Divide, Negate, Power, Square, Root, Sqrt, Abs, Round
|
|
69
|
+
* **Arithmetic:** Add, Sum, Subtract, Multiply, Divide, Negate, Power, Square, Root, Sqrt, Abs, Round, Floor, Ceil
|
|
63
70
|
* **Trigonometry:** Sin, Cos, Tan, Arcsin, Arccos, Arctan
|
|
64
71
|
* **Logarithms:** Log, Log2, Log10, Exp
|
|
65
72
|
* **Comparison:** Equal, StrictEqual, NotEqual, Greater, GreaterEqual, Less, LessEqual
|
|
66
|
-
* **Logic & Sets:** Any, All, Not, In, NotIn, ContainsAnyOf, ContainsAllOf, ContainsNoneOf
|
|
73
|
+
* **Logic & Sets:** Any, All, Not, And, Or, In, NotIn, ContainsAnyOf, ContainsAllOf, ContainsNoneOf
|
|
67
74
|
* **Statistics:** Average, Max, Min, Median, Length
|
|
68
|
-
* **
|
|
75
|
+
* **Functional Programming:** Map, Reduce, Filter
|
|
76
|
+
* **Arrays:** Array creation, GenerateRange, AtIndex, Slice, Appended, CumulativeSum, CumulativeProduct
|
|
69
77
|
* **Control Flow:** If statements, Switch-Case, Constants definition
|
|
70
78
|
* **Type Conversion:** Int, Float, Str, IsDefined
|
|
71
|
-
* **Date/Time:** Strptime, Strftime, Today, Now, TimeDelta functions
|
|
72
|
-
* **
|
|
79
|
+
* **Date/Time:** Strptime, Strftime, Today, Now, TimeDelta functions (Weeks, Days, Hours, Minutes)
|
|
80
|
+
* **Integration:** TrapezoidalIntegrate (requires numpy), Interp, FindIntervalIndex, Variable references
|
|
81
|
+
* **Advanced:** HasMatchingSublist for pattern matching
|
|
73
82
|
* **Constants:** Pi
|
|
74
83
|
|
|
75
84
|
[View complete documentation with examples →](https://github.com/LongenesisLtd/mathjson-solver/blob/main/docs/README.md)
|
|
@@ -136,6 +145,10 @@ We welcome contributions! Please feel free to:
|
|
|
136
145
|
|
|
137
146
|
[View license information](https://github.com/LongenesisLtd/mathjson-solver/blob/main/LICENSE)
|
|
138
147
|
|
|
148
|
+
## References
|
|
149
|
+
|
|
150
|
+
This implementation was inspired by the [CortexJS Compute Engine](https://cortexjs.io/compute-engine/), though designed as an independent implementation focused on our specific use cases.
|
|
151
|
+
|
|
139
152
|
---
|
|
140
153
|
|
|
141
154
|
Made with ❤️ by [Longenesis](https://longenesis.com/team)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = mathjson-solver
|
|
3
|
-
version = 1.
|
|
3
|
+
version = 1.18.0
|
|
4
4
|
author = Martins Mednis
|
|
5
5
|
author_email = mrt@mednis.info
|
|
6
6
|
description = Utilities for MathJSON evaluation
|
|
@@ -11,8 +11,8 @@ project_urls =
|
|
|
11
11
|
Bug Tracker = https://github.com/LongenesisLtd/mathjson-solver/issues
|
|
12
12
|
classifiers =
|
|
13
13
|
Programming Language :: Python :: 3
|
|
14
|
-
License :: OSI Approved :: MIT License
|
|
15
14
|
Operating System :: OS Independent
|
|
15
|
+
license_expr = MIT
|
|
16
16
|
|
|
17
17
|
[options]
|
|
18
18
|
package_dir =
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name="mathjson-solver",
|
|
8
|
-
version="1.
|
|
8
|
+
version="1.18.0",
|
|
9
9
|
author="Martins Mednis",
|
|
10
10
|
author_email="mrt@mednis.info",
|
|
11
11
|
description="Utilities for MathJSON evaluation",
|
|
@@ -15,9 +15,9 @@ setuptools.setup(
|
|
|
15
15
|
project_urls={
|
|
16
16
|
"Bug Tracker": "https://github.com/LongenesisLtd/mathjson-solver/issues",
|
|
17
17
|
},
|
|
18
|
+
license_expr="MIT",
|
|
18
19
|
classifiers=[
|
|
19
20
|
"Programming Language :: Python :: 3",
|
|
20
|
-
"License :: OSI Approved :: MIT License",
|
|
21
21
|
"Operating System :: OS Independent",
|
|
22
22
|
],
|
|
23
23
|
package_dir={"": "src"},
|
|
@@ -17,6 +17,22 @@ except ImportError:
|
|
|
17
17
|
NoneType = type(None)
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
def _try_parse_datetime(value):
|
|
21
|
+
"""Try to parse a string as datetime or date. Returns original value if not parseable."""
|
|
22
|
+
if isinstance(value, (datetime.datetime, datetime.date)):
|
|
23
|
+
return value
|
|
24
|
+
if isinstance(value, str):
|
|
25
|
+
try:
|
|
26
|
+
return datetime.datetime.fromisoformat(value)
|
|
27
|
+
except ValueError:
|
|
28
|
+
pass
|
|
29
|
+
try:
|
|
30
|
+
return datetime.date.fromisoformat(value)
|
|
31
|
+
except ValueError:
|
|
32
|
+
pass
|
|
33
|
+
return value
|
|
34
|
+
|
|
35
|
+
|
|
20
36
|
# def find_interpolation_bounds(
|
|
21
37
|
# l: list, target: int | float
|
|
22
38
|
# ) -> Union[Union[int, float], tuple[Union[int, float], Union[int, float]]]:
|
|
@@ -70,6 +86,16 @@ def _CumulativeProduct(l: list) -> list:
|
|
|
70
86
|
return res
|
|
71
87
|
|
|
72
88
|
|
|
89
|
+
def _CumulativeSum(l: list) -> list:
|
|
90
|
+
res = []
|
|
91
|
+
for i, x in enumerate(l):
|
|
92
|
+
if i == 0:
|
|
93
|
+
res.append(x)
|
|
94
|
+
else:
|
|
95
|
+
res.append(reduce(lambda a, b: a + b, l[: i + 1]))
|
|
96
|
+
return res
|
|
97
|
+
|
|
98
|
+
|
|
73
99
|
def find_interpolation_bounds_indexes(
|
|
74
100
|
l: list, target: int | float
|
|
75
101
|
) -> Union[Union[int, float], tuple[Union[int, float], Union[int, float]]]:
|
|
@@ -284,16 +310,19 @@ def create_mathjson_solver(solver_parameters):
|
|
|
284
310
|
if i == 0:
|
|
285
311
|
tmp = res
|
|
286
312
|
else:
|
|
313
|
+
# Handle datetime string + timedelta
|
|
314
|
+
if isinstance(res, datetime.timedelta):
|
|
315
|
+
tmp = _try_parse_datetime(tmp)
|
|
316
|
+
elif isinstance(tmp, datetime.timedelta):
|
|
317
|
+
res = _try_parse_datetime(res)
|
|
287
318
|
try:
|
|
288
319
|
tmp = tmp + res
|
|
289
320
|
except TypeError:
|
|
290
321
|
pass
|
|
291
322
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
# l_res.append(res)
|
|
296
|
-
|
|
323
|
+
# Convert datetime result back to string
|
|
324
|
+
if isinstance(tmp, (datetime.datetime, datetime.date)):
|
|
325
|
+
return tmp.isoformat()
|
|
297
326
|
return tmp
|
|
298
327
|
|
|
299
328
|
# tmp = 0
|
|
@@ -324,6 +353,22 @@ def create_mathjson_solver(solver_parameters):
|
|
|
324
353
|
l_res.append(res)
|
|
325
354
|
return Add(l_res)
|
|
326
355
|
|
|
356
|
+
def Subtract(s):
|
|
357
|
+
values = [f(x, c) for x in s[1:]]
|
|
358
|
+
# Convert datetime strings if we're dealing with timedelta
|
|
359
|
+
converted = []
|
|
360
|
+
for i, v in enumerate(values):
|
|
361
|
+
if isinstance(v, datetime.timedelta):
|
|
362
|
+
converted.append(v)
|
|
363
|
+
elif any(isinstance(other, datetime.timedelta) for other in values):
|
|
364
|
+
converted.append(_try_parse_datetime(v))
|
|
365
|
+
else:
|
|
366
|
+
converted.append(v)
|
|
367
|
+
result = reduce(lambda a, b: a - b, converted)
|
|
368
|
+
if isinstance(result, (datetime.datetime, datetime.date)):
|
|
369
|
+
return result.isoformat()
|
|
370
|
+
return result
|
|
371
|
+
|
|
327
372
|
def Max(s):
|
|
328
373
|
if isinstance(s[1], str):
|
|
329
374
|
return max([f(x, c) for x in f(s[1], c) if is_numeric(f(x, c))])
|
|
@@ -360,10 +405,16 @@ def create_mathjson_solver(solver_parameters):
|
|
|
360
405
|
return len([x for x in s[1][1:]])
|
|
361
406
|
|
|
362
407
|
def Any(s):
|
|
363
|
-
|
|
408
|
+
evaluated = f(s[1], c)
|
|
409
|
+
if isinstance(evaluated, list) and evaluated[0] == "Array":
|
|
410
|
+
return any([f(x, c) for x in evaluated[1:]])
|
|
411
|
+
raise ValueError("Parameter 1 must be an array.")
|
|
364
412
|
|
|
365
413
|
def All(s):
|
|
366
|
-
|
|
414
|
+
evaluated = f(s[1], c)
|
|
415
|
+
if isinstance(evaluated, list) and evaluated[0] == "Array":
|
|
416
|
+
return all([f(x, c) for x in evaluated[1:]])
|
|
417
|
+
raise ValueError("Parameter 1 must be an array.")
|
|
367
418
|
|
|
368
419
|
def Int(s):
|
|
369
420
|
try:
|
|
@@ -374,6 +425,12 @@ def create_mathjson_solver(solver_parameters):
|
|
|
374
425
|
def Float(s):
|
|
375
426
|
return float(f(s[1], c))
|
|
376
427
|
|
|
428
|
+
def Floor(s):
|
|
429
|
+
return math.floor(f(s[1], c))
|
|
430
|
+
|
|
431
|
+
def Ceil(s):
|
|
432
|
+
return math.ceil(f(s[1], c))
|
|
433
|
+
|
|
377
434
|
def Constants(s):
|
|
378
435
|
for x in s[1:-1]:
|
|
379
436
|
c[x[0]] = f(x[1], c)
|
|
@@ -556,18 +613,18 @@ def create_mathjson_solver(solver_parameters):
|
|
|
556
613
|
def Strptime(s):
|
|
557
614
|
datetime_str = f(s[1], c)
|
|
558
615
|
parameters = f(s[2], c)
|
|
559
|
-
return datetime.datetime.strptime(datetime_str, parameters)
|
|
616
|
+
return datetime.datetime.strptime(datetime_str, parameters).isoformat()
|
|
560
617
|
|
|
561
618
|
def Strftime(s):
|
|
562
|
-
dt = f(s[1], c)
|
|
619
|
+
dt = _try_parse_datetime(f(s[1], c))
|
|
563
620
|
parameters = f(s[2], c)
|
|
564
621
|
return dt.strftime(parameters)
|
|
565
622
|
|
|
566
623
|
def Now(s):
|
|
567
|
-
return datetime.datetime.now()
|
|
624
|
+
return datetime.datetime.now().isoformat()
|
|
568
625
|
|
|
569
626
|
def Today(s):
|
|
570
|
-
return datetime.date.today()
|
|
627
|
+
return datetime.date.today().isoformat()
|
|
571
628
|
|
|
572
629
|
def TimeDeltaDays(s):
|
|
573
630
|
return datetime.timedelta(days=f(s[1], c))
|
|
@@ -629,6 +686,26 @@ def create_mathjson_solver(solver_parameters):
|
|
|
629
686
|
except TypeError:
|
|
630
687
|
return False
|
|
631
688
|
|
|
689
|
+
def BooleanAnd(s):
|
|
690
|
+
"""
|
|
691
|
+
Boolean AND operation.
|
|
692
|
+
["And", condition1, condition2, ...]
|
|
693
|
+
"""
|
|
694
|
+
for x in s[1:]:
|
|
695
|
+
if not f(x, c):
|
|
696
|
+
return False
|
|
697
|
+
return True
|
|
698
|
+
|
|
699
|
+
def BooleanOr(s):
|
|
700
|
+
"""
|
|
701
|
+
Boolean OR operation.
|
|
702
|
+
["Or", condition1, condition2, ...]
|
|
703
|
+
"""
|
|
704
|
+
for x in s[1:]:
|
|
705
|
+
if f(x, c):
|
|
706
|
+
return True
|
|
707
|
+
return False
|
|
708
|
+
|
|
632
709
|
# sin, cos, tan, arcsin, arccos, arctan
|
|
633
710
|
def Sin(s):
|
|
634
711
|
return math.sin(f(s[1], c))
|
|
@@ -840,6 +917,18 @@ def create_mathjson_solver(solver_parameters):
|
|
|
840
917
|
return ["Array"] + _CumulativeProduct(array)
|
|
841
918
|
# return _CumulativeProduct(array)
|
|
842
919
|
|
|
920
|
+
def CumulativeSum(s):
|
|
921
|
+
"""
|
|
922
|
+
["CumulativeSum", array]
|
|
923
|
+
The `array` must be an array of numeric values.
|
|
924
|
+
"""
|
|
925
|
+
array = f(s[1], c)
|
|
926
|
+
if not (isinstance(array, list) and array[0] == "Array"):
|
|
927
|
+
raise ValueError("Parameter 1 must be an array.")
|
|
928
|
+
array = [f(x, c) for x in array[1:]]
|
|
929
|
+
return ["Array"] + _CumulativeSum(array)
|
|
930
|
+
# return
|
|
931
|
+
|
|
843
932
|
def Interp(s):
|
|
844
933
|
"""
|
|
845
934
|
["Interp", x_array, y_array, target_x]
|
|
@@ -900,12 +989,53 @@ def create_mathjson_solver(solver_parameters):
|
|
|
900
989
|
|
|
901
990
|
# return total_area
|
|
902
991
|
|
|
992
|
+
def Reduce(s):
|
|
993
|
+
"""
|
|
994
|
+
["Reduce", list, initial_value, function, str_name_of_accumulator, str_name_of_current, str_name_of_index]
|
|
995
|
+
"""
|
|
996
|
+
the_list = f(s[1], c)[1:]
|
|
997
|
+
initial_value = f(s[2], c)
|
|
998
|
+
function_expression = s[3]
|
|
999
|
+
|
|
1000
|
+
_accumulator = s[4]
|
|
1001
|
+
name_accumulator = _accumulator[1]
|
|
1002
|
+
|
|
1003
|
+
_current = s[5]
|
|
1004
|
+
name_current = _current[1]
|
|
1005
|
+
|
|
1006
|
+
_index = s[6]
|
|
1007
|
+
name_index = _index[1]
|
|
1008
|
+
|
|
1009
|
+
c[name_accumulator] = initial_value
|
|
1010
|
+
|
|
1011
|
+
for i, x in enumerate(the_list):
|
|
1012
|
+
c[name_current] = x
|
|
1013
|
+
c[name_index] = i
|
|
1014
|
+
c[name_accumulator] = f(function_expression, c)
|
|
1015
|
+
|
|
1016
|
+
return c[name_accumulator]
|
|
1017
|
+
|
|
1018
|
+
def Appended(s):
|
|
1019
|
+
"""
|
|
1020
|
+
["Appended", array, value]
|
|
1021
|
+
The `array` must be an array of values.
|
|
1022
|
+
The `value` is the value to append to the array.
|
|
1023
|
+
"""
|
|
1024
|
+
array = f(s[1], c)
|
|
1025
|
+
|
|
1026
|
+
if not (isinstance(array, list) and array[0] == "Array"):
|
|
1027
|
+
raise ValueError("Parameter 1 must be an array.")
|
|
1028
|
+
|
|
1029
|
+
value = f(s[2], c)
|
|
1030
|
+
|
|
1031
|
+
array = [x for x in array[1:]]
|
|
1032
|
+
array.append(value)
|
|
1033
|
+
return ["Array"] + array
|
|
1034
|
+
|
|
903
1035
|
constructs = {
|
|
904
1036
|
"Sum": Sum,
|
|
905
1037
|
"Add": Add,
|
|
906
|
-
"Subtract":
|
|
907
|
-
lambda a, b: a - b, [f(x, c) for x in s[1:]]
|
|
908
|
-
),
|
|
1038
|
+
"Subtract": Subtract,
|
|
909
1039
|
"Constants": Constants,
|
|
910
1040
|
"Switch": Switch,
|
|
911
1041
|
"StrictSwitch": StrictSwitch,
|
|
@@ -939,6 +1069,8 @@ def create_mathjson_solver(solver_parameters):
|
|
|
939
1069
|
# "NotEqual": lambda s: f(s[1], c) != f(s[2], c),
|
|
940
1070
|
"NotEqual": lambda s: comparison_safe_converter(f(s[1], c))
|
|
941
1071
|
!= comparison_safe_converter(f(s[2], c)),
|
|
1072
|
+
"And": BooleanAnd,
|
|
1073
|
+
"Or": BooleanOr,
|
|
942
1074
|
"Abs": lambda s: abs(f(s[1], c)),
|
|
943
1075
|
"Round": lambda s: (
|
|
944
1076
|
round(f(s[1], c), f(s[2], c))
|
|
@@ -964,6 +1096,8 @@ def create_mathjson_solver(solver_parameters):
|
|
|
964
1096
|
"ContainsNoneOf": Contains_none_of,
|
|
965
1097
|
"Int": Int,
|
|
966
1098
|
"Float": Float,
|
|
1099
|
+
"Floor": Floor,
|
|
1100
|
+
"Ceil": Ceil,
|
|
967
1101
|
"Str": Str,
|
|
968
1102
|
"Not": Not,
|
|
969
1103
|
# "IsDefined": lambda s: s[1] in c,
|
|
@@ -992,9 +1126,12 @@ def create_mathjson_solver(solver_parameters):
|
|
|
992
1126
|
"AtIndex": AtIndex,
|
|
993
1127
|
"Slice": Slice,
|
|
994
1128
|
"CumulativeProduct": CumulativeProduct,
|
|
1129
|
+
"CumulativeSum": CumulativeSum,
|
|
995
1130
|
"Interp": Interp,
|
|
996
1131
|
"FindIntervalIndex": FindIntervalIndex,
|
|
997
1132
|
"TrapezoidalIntegrate": TrapezoidalIntegrate,
|
|
1133
|
+
"Reduce": Reduce,
|
|
1134
|
+
"Appended": Appended,
|
|
998
1135
|
"Sin": Sin,
|
|
999
1136
|
"Cos": Cos,
|
|
1000
1137
|
"Tan": Tan,
|
|
@@ -1066,6 +1203,8 @@ def extract_variables(s: Union[list, int, float, str], li: set, ignore_list: set
|
|
|
1066
1203
|
"Less",
|
|
1067
1204
|
"LessEqual",
|
|
1068
1205
|
"NotEqual",
|
|
1206
|
+
"And",
|
|
1207
|
+
"Or",
|
|
1069
1208
|
"Abs",
|
|
1070
1209
|
"Round",
|
|
1071
1210
|
"Max",
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mathjson-solver
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.18.0
|
|
4
4
|
Summary: Utilities for MathJSON evaluation
|
|
5
5
|
Home-page: https://github.com/LongenesisLtd/mathjson-solver
|
|
6
6
|
Author: Martins Mednis
|
|
7
7
|
Author-email: mrt@mednis.info
|
|
8
8
|
Project-URL: Bug Tracker, https://github.com/LongenesisLtd/mathjson-solver/issues
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
10
|
Classifier: Operating System :: OS Independent
|
|
12
11
|
Requires-Python: >=3.6
|
|
13
12
|
Description-Content-Type: text/markdown
|
|
@@ -33,8 +32,6 @@ A reliable Python library for numerically evaluating mathematical expressions in
|
|
|
33
32
|
|
|
34
33
|
**What is MathJSON?** MathJSON represents mathematical expressions as JSON arrays, like `["Add", 1, 2, 3]` for 1+2+3. This format is safe, structured, and easy to generate programmatically.
|
|
35
34
|
|
|
36
|
-
Inspired by [CortexJS Compute Engine](https://cortexjs.io/compute-engine/) though designed as an independent implementation focused on our specific use cases.
|
|
37
|
-
|
|
38
35
|
## Table of Contents
|
|
39
36
|
- [Installation](#installation)
|
|
40
37
|
- [Quick Start](#quick-start)
|
|
@@ -80,21 +77,32 @@ except MathJSONException as e:
|
|
|
80
77
|
# Math error: Problem in Divide. ['Divide', 1, 0]. division by zero
|
|
81
78
|
```
|
|
82
79
|
|
|
80
|
+
**Think Functional:** MathJSON Solver embraces functional programming principles. Instead of writing loops and modifying variables, you compose expressions that transform data. Functions like `Map`, `Reduce`, and `Filter` let you process arrays elegantly, while immutable operations ensure predictable, side-effect-free calculations. Don't worry if you're new to functional programming — the examples will guide you naturally into this powerful paradigm.
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
# Functional approach: transform data with expressions
|
|
84
|
+
solver(["Map", ["Array", 1, 2, 3, 4], ["Multiply"], 2]) # [2, 4, 6, 8]
|
|
85
|
+
solver(["Reduce", ["Array", 1, 2, 3, 4], 0, ["Add", "acc", "item"],
|
|
86
|
+
["Variable", "acc"], ["Variable", "item"], ["Variable", "i"]]) # 10
|
|
87
|
+
```
|
|
88
|
+
|
|
83
89
|
## Supported Operations
|
|
84
90
|
|
|
85
91
|
The library supports a comprehensive set of mathematical operations:
|
|
86
92
|
|
|
87
|
-
* **Arithmetic:** Add, Sum, Subtract, Multiply, Divide, Negate, Power, Square, Root, Sqrt, Abs, Round
|
|
93
|
+
* **Arithmetic:** Add, Sum, Subtract, Multiply, Divide, Negate, Power, Square, Root, Sqrt, Abs, Round, Floor, Ceil
|
|
88
94
|
* **Trigonometry:** Sin, Cos, Tan, Arcsin, Arccos, Arctan
|
|
89
95
|
* **Logarithms:** Log, Log2, Log10, Exp
|
|
90
96
|
* **Comparison:** Equal, StrictEqual, NotEqual, Greater, GreaterEqual, Less, LessEqual
|
|
91
|
-
* **Logic & Sets:** Any, All, Not, In, NotIn, ContainsAnyOf, ContainsAllOf, ContainsNoneOf
|
|
97
|
+
* **Logic & Sets:** Any, All, Not, And, Or, In, NotIn, ContainsAnyOf, ContainsAllOf, ContainsNoneOf
|
|
92
98
|
* **Statistics:** Average, Max, Min, Median, Length
|
|
93
|
-
* **
|
|
99
|
+
* **Functional Programming:** Map, Reduce, Filter
|
|
100
|
+
* **Arrays:** Array creation, GenerateRange, AtIndex, Slice, Appended, CumulativeSum, CumulativeProduct
|
|
94
101
|
* **Control Flow:** If statements, Switch-Case, Constants definition
|
|
95
102
|
* **Type Conversion:** Int, Float, Str, IsDefined
|
|
96
|
-
* **Date/Time:** Strptime, Strftime, Today, Now, TimeDelta functions
|
|
97
|
-
* **
|
|
103
|
+
* **Date/Time:** Strptime, Strftime, Today, Now, TimeDelta functions (Weeks, Days, Hours, Minutes)
|
|
104
|
+
* **Integration:** TrapezoidalIntegrate (requires numpy), Interp, FindIntervalIndex, Variable references
|
|
105
|
+
* **Advanced:** HasMatchingSublist for pattern matching
|
|
98
106
|
* **Constants:** Pi
|
|
99
107
|
|
|
100
108
|
[View complete documentation with examples →](https://github.com/LongenesisLtd/mathjson-solver/blob/main/docs/README.md)
|
|
@@ -161,6 +169,10 @@ We welcome contributions! Please feel free to:
|
|
|
161
169
|
|
|
162
170
|
[View license information](https://github.com/LongenesisLtd/mathjson-solver/blob/main/LICENSE)
|
|
163
171
|
|
|
172
|
+
## References
|
|
173
|
+
|
|
174
|
+
This implementation was inspired by the [CortexJS Compute Engine](https://cortexjs.io/compute-engine/), though designed as an independent implementation focused on our specific use cases.
|
|
175
|
+
|
|
164
176
|
---
|
|
165
177
|
|
|
166
178
|
Made with ❤️ by [Longenesis](https://longenesis.com/team)
|
|
@@ -9,10 +9,10 @@ src/mathjson_solver.egg-info/PKG-INFO
|
|
|
9
9
|
src/mathjson_solver.egg-info/SOURCES.txt
|
|
10
10
|
src/mathjson_solver.egg-info/dependency_links.txt
|
|
11
11
|
src/mathjson_solver.egg-info/top_level.txt
|
|
12
|
-
tests/test_CumulativeProduct.py
|
|
13
|
-
tests/test_Slice.py
|
|
14
12
|
tests/test_TrapezoidalIntegratel.py
|
|
15
13
|
tests/test_atindex.py
|
|
14
|
+
tests/test_cumulative.py
|
|
15
|
+
tests/test_datetime.py
|
|
16
16
|
tests/test_equal.py
|
|
17
17
|
tests/test_exceptions.py
|
|
18
18
|
tests/test_extract_variables.py
|
|
@@ -20,7 +20,10 @@ tests/test_findinterval.py
|
|
|
20
20
|
tests/test_gail_model.py
|
|
21
21
|
tests/test_interpolate.py
|
|
22
22
|
tests/test_range.py
|
|
23
|
+
tests/test_reduce_simple.py
|
|
23
24
|
tests/test_scalars.py
|
|
24
25
|
tests/test_sets.py
|
|
25
26
|
tests/test_simple_cases.py
|
|
27
|
+
tests/test_slice.py
|
|
28
|
+
tests/test_state_tuples_reduce.py
|
|
26
29
|
tests/test_with_pytest.py
|
|
@@ -16,3 +16,14 @@ def test_CumulativeProduct1():
|
|
|
16
16
|
solver = create_solver(parameters)
|
|
17
17
|
# assert solver(expression) == expected_result
|
|
18
18
|
assert solver(expression) == expected_result
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_CumulativeSum1():
|
|
22
|
+
parameters = {"test_array": ["Array", 1, 2, 3, 4, 5]}
|
|
23
|
+
|
|
24
|
+
expression = ["CumulativeSum", "test_array"]
|
|
25
|
+
|
|
26
|
+
expected_result = ["Array", 1, 3, 6, 10, 15]
|
|
27
|
+
solver = create_solver(parameters)
|
|
28
|
+
# assert solver(expression) == expected_result
|
|
29
|
+
assert solver(expression) == expected_result
|