mathjson-solver 1.10.0__tar.gz → 1.12.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.12.0/PKG-INFO +83 -0
- mathjson_solver-1.12.0/README.md +59 -0
- {mathjson_solver-1.10.0 → mathjson_solver-1.12.0}/setup.cfg +1 -1
- {mathjson_solver-1.10.0 → mathjson_solver-1.12.0}/setup.py +1 -1
- {mathjson_solver-1.10.0 → mathjson_solver-1.12.0}/src/mathjson_solver/__main__.py +106 -55
- mathjson_solver-1.12.0/src/mathjson_solver.egg-info/PKG-INFO +83 -0
- {mathjson_solver-1.10.0 → mathjson_solver-1.12.0}/tests/test_with_pytest.py +174 -5
- mathjson_solver-1.10.0/PKG-INFO +0 -278
- mathjson_solver-1.10.0/README.md +0 -254
- mathjson_solver-1.10.0/src/mathjson_solver.egg-info/PKG-INFO +0 -278
- {mathjson_solver-1.10.0 → mathjson_solver-1.12.0}/LICENSE +0 -0
- {mathjson_solver-1.10.0 → mathjson_solver-1.12.0}/pyproject.toml +0 -0
- {mathjson_solver-1.10.0 → mathjson_solver-1.12.0}/src/mathjson_solver/__init__.py +0 -0
- {mathjson_solver-1.10.0 → mathjson_solver-1.12.0}/src/mathjson_solver.egg-info/SOURCES.txt +0 -0
- {mathjson_solver-1.10.0 → mathjson_solver-1.12.0}/src/mathjson_solver.egg-info/dependency_links.txt +0 -0
- {mathjson_solver-1.10.0 → mathjson_solver-1.12.0}/src/mathjson_solver.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: mathjson-solver
|
|
3
|
+
Version: 1.12.0
|
|
4
|
+
Summary: Utilities for MathJSON evaluation
|
|
5
|
+
Home-page: https://github.com/LongenesisLtd/mathjson-solver
|
|
6
|
+
Author: Martins Mednis
|
|
7
|
+
Author-email: mrt@mednis.info
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/LongenesisLtd/mathjson-solver/issues
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.6
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: project-url
|
|
22
|
+
Dynamic: requires-python
|
|
23
|
+
Dynamic: summary
|
|
24
|
+
|
|
25
|
+
# MathJSON Solver
|
|
26
|
+
|
|
27
|
+
[](https://pypi.org/project/mathjson-solver/)
|
|
28
|
+
[](https://pepy.tech/projects/mathjson-solver)
|
|
29
|
+

|
|
30
|
+
|
|
31
|
+
_MathJSON Solver_ is a Python module to numerically evaluate MathJSON expressions, like `["Add", 1, 2]`. It is developed by [Longenesis](https://longenesis.com/team) to enable numerical evaluation of user provided mathematical expressions in Longenesis digital health products. Its development was inspired by [CortexJS](https://cortexjs.io/compute-engine/) Compute Engine.
|
|
32
|
+
|
|
33
|
+
Please ask questions and share feedback in our Gitter chat [https://gitter.im/mathjson-solver/community](https://gitter.im/mathjson-solver/community).
|
|
34
|
+
[](https://gitter.im/mathjson-solver/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
|
35
|
+
|
|
36
|
+
## How to use
|
|
37
|
+
```python
|
|
38
|
+
from mathjson_solver import create_solver
|
|
39
|
+
|
|
40
|
+
parameters = {"x": 2, "y": 3}
|
|
41
|
+
expression = ["Add", "x", "y", 4]
|
|
42
|
+
|
|
43
|
+
solver = create_solver(parameters)
|
|
44
|
+
answer = solver(expression)
|
|
45
|
+
|
|
46
|
+
print(answer)
|
|
47
|
+
# 9, because 2+3+4=9
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Currently supported constructs
|
|
51
|
+
Find the full list of supported constructs in the [docs/README.md](https://github.com/LongenesisLtd/mathjson-solver/blob/main/docs/README.md).
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Exception handling
|
|
55
|
+
|
|
56
|
+
A `MathJSONException` is raised when expression cannot be evaluated. Import `MathJSONException` to handle it:
|
|
57
|
+
```python
|
|
58
|
+
from mathjson_solver import create_solver, MathJSONException
|
|
59
|
+
|
|
60
|
+
solver = create_solver({})
|
|
61
|
+
try:
|
|
62
|
+
solver(["Divide", 1, 0])
|
|
63
|
+
except MathJSONException:
|
|
64
|
+
pass
|
|
65
|
+
# invoke your own exception logger here
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Left unhandled, the exception will look like `MathJSONException("Problem in Divide. ['Divide', 1, 0]. division by zero")`.
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## How to run tests
|
|
72
|
+
Make sure you have `pytest` installed. Then `cd` into project directory and run:
|
|
73
|
+
```bash
|
|
74
|
+
pytest
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Contributing Code
|
|
78
|
+
|
|
79
|
+
We welcome your contributions in the form of pull requests.
|
|
80
|
+
|
|
81
|
+
1. Fork the repo;
|
|
82
|
+
2. Make improvements;
|
|
83
|
+
3. Make a pull request to share your improvements with the community and to include it into official release.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# MathJSON Solver
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/mathjson-solver/)
|
|
4
|
+
[](https://pepy.tech/projects/mathjson-solver)
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
_MathJSON Solver_ is a Python module to numerically evaluate MathJSON expressions, like `["Add", 1, 2]`. It is developed by [Longenesis](https://longenesis.com/team) to enable numerical evaluation of user provided mathematical expressions in Longenesis digital health products. Its development was inspired by [CortexJS](https://cortexjs.io/compute-engine/) Compute Engine.
|
|
8
|
+
|
|
9
|
+
Please ask questions and share feedback in our Gitter chat [https://gitter.im/mathjson-solver/community](https://gitter.im/mathjson-solver/community).
|
|
10
|
+
[](https://gitter.im/mathjson-solver/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
|
11
|
+
|
|
12
|
+
## How to use
|
|
13
|
+
```python
|
|
14
|
+
from mathjson_solver import create_solver
|
|
15
|
+
|
|
16
|
+
parameters = {"x": 2, "y": 3}
|
|
17
|
+
expression = ["Add", "x", "y", 4]
|
|
18
|
+
|
|
19
|
+
solver = create_solver(parameters)
|
|
20
|
+
answer = solver(expression)
|
|
21
|
+
|
|
22
|
+
print(answer)
|
|
23
|
+
# 9, because 2+3+4=9
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Currently supported constructs
|
|
27
|
+
Find the full list of supported constructs in the [docs/README.md](https://github.com/LongenesisLtd/mathjson-solver/blob/main/docs/README.md).
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## Exception handling
|
|
31
|
+
|
|
32
|
+
A `MathJSONException` is raised when expression cannot be evaluated. Import `MathJSONException` to handle it:
|
|
33
|
+
```python
|
|
34
|
+
from mathjson_solver import create_solver, MathJSONException
|
|
35
|
+
|
|
36
|
+
solver = create_solver({})
|
|
37
|
+
try:
|
|
38
|
+
solver(["Divide", 1, 0])
|
|
39
|
+
except MathJSONException:
|
|
40
|
+
pass
|
|
41
|
+
# invoke your own exception logger here
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Left unhandled, the exception will look like `MathJSONException("Problem in Divide. ['Divide', 1, 0]. division by zero")`.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
## How to run tests
|
|
48
|
+
Make sure you have `pytest` installed. Then `cd` into project directory and run:
|
|
49
|
+
```bash
|
|
50
|
+
pytest
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Contributing Code
|
|
54
|
+
|
|
55
|
+
We welcome your contributions in the form of pull requests.
|
|
56
|
+
|
|
57
|
+
1. Fork the repo;
|
|
58
|
+
2. Make improvements;
|
|
59
|
+
3. Make a pull request to share your improvements with the community and to include it into official release.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import numbers
|
|
2
|
+
from types import NoneType
|
|
2
3
|
from typing import Union
|
|
3
4
|
from functools import reduce
|
|
4
5
|
import math
|
|
@@ -26,17 +27,17 @@ class MathJSONException(Exception):
|
|
|
26
27
|
return f"Problem in {self.construct}. {self.expr}. {m}"
|
|
27
28
|
|
|
28
29
|
|
|
29
|
-
def requires_array(func):
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
# def requires_array(func):
|
|
31
|
+
# def inner1(*args, **kwargs):
|
|
32
|
+
# try:
|
|
33
|
+
# if args[0][1][0] == "Array" and len(args[0][1]) > 0:
|
|
34
|
+
# return func(*args, **kwargs)
|
|
35
|
+
# else:
|
|
36
|
+
# raise ValueError(f"'{func.__name__}' should receive a list")
|
|
37
|
+
# except TypeError:
|
|
38
|
+
# raise ValueError(f"'{func.__name__}' really should receive a list")
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
# return inner1
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
def is_numeric(x):
|
|
@@ -92,40 +93,51 @@ def has_matching_sublist(
|
|
|
92
93
|
return count >= required_match_count
|
|
93
94
|
|
|
94
95
|
|
|
95
|
-
def has_sublist2(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
) -> bool:
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
96
|
+
# def has_sublist2(
|
|
97
|
+
# *,
|
|
98
|
+
# my_list: list,
|
|
99
|
+
# required_match_count: int,
|
|
100
|
+
# position: int,
|
|
101
|
+
# contiguous: bool,
|
|
102
|
+
# condition: callable,
|
|
103
|
+
# ) -> bool:
|
|
104
|
+
# if contiguous:
|
|
105
|
+
# # Check for contiguous matches based on position
|
|
106
|
+
# if position == 0:
|
|
107
|
+
# # Check if the beginning of the list matches
|
|
108
|
+
# count = sum(1 for x in my_list[:required_match_count] if condition(x))
|
|
109
|
+
# return count == required_match_count
|
|
110
|
+
# elif position > 0:
|
|
111
|
+
# # Skip the first `position` elements
|
|
112
|
+
# count = sum(
|
|
113
|
+
# 1
|
|
114
|
+
# for x in my_list[position : position + required_match_count]
|
|
115
|
+
# if condition(x)
|
|
116
|
+
# )
|
|
117
|
+
# return count == required_match_count
|
|
118
|
+
# elif position == -1:
|
|
119
|
+
# # Check if the end of the list matches
|
|
120
|
+
# count = sum(1 for x in my_list[-required_match_count:] if condition(x))
|
|
121
|
+
# return count == required_match_count
|
|
122
|
+
# elif position < -1:
|
|
123
|
+
# # Skip the last `abs(position)` elements
|
|
124
|
+
# count = sum(1 for x in my_list[:position] if condition(x))
|
|
125
|
+
# return count == required_match_count
|
|
126
|
+
# else:
|
|
127
|
+
# # Check for non-contiguous matches
|
|
128
|
+
# count = sum(1 for x in my_list if condition(x))
|
|
129
|
+
# return count >= required_match_count
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def comparison_safe_converter(x):
|
|
133
|
+
if type(x) in [int, float, str]:
|
|
134
|
+
return f"{x}"
|
|
135
|
+
elif type(x) in [bool, NoneType]:
|
|
136
|
+
if x:
|
|
137
|
+
return True
|
|
138
|
+
else:
|
|
139
|
+
return False
|
|
140
|
+
return x
|
|
129
141
|
|
|
130
142
|
|
|
131
143
|
def create_mathjson_solver(solver_parameters):
|
|
@@ -147,7 +159,7 @@ def create_mathjson_solver(solver_parameters):
|
|
|
147
159
|
tmp = 0
|
|
148
160
|
for i, x in enumerate(s[1:]):
|
|
149
161
|
res = f(x, c)
|
|
150
|
-
if i ==0:
|
|
162
|
+
if i == 0:
|
|
151
163
|
tmp = res
|
|
152
164
|
else:
|
|
153
165
|
tmp = tmp + res
|
|
@@ -177,14 +189,12 @@ def create_mathjson_solver(solver_parameters):
|
|
|
177
189
|
l_res.append(res)
|
|
178
190
|
return sum(l_res)
|
|
179
191
|
|
|
180
|
-
# @requires_array
|
|
181
192
|
def Max(s):
|
|
182
193
|
if isinstance(s[1], str):
|
|
183
194
|
return max([f(x, c) for x in f(s[1], c) if is_numeric(f(x, c))])
|
|
184
195
|
else:
|
|
185
196
|
return max([f(x, c) for x in s[1][1:] if is_numeric(f(x, c))])
|
|
186
197
|
|
|
187
|
-
# @requires_array
|
|
188
198
|
def Min(s):
|
|
189
199
|
if isinstance(s[1], str):
|
|
190
200
|
return min([f(x, c) for x in f(s[1], c) if is_numeric(f(x, c))])
|
|
@@ -203,14 +213,12 @@ def create_mathjson_solver(solver_parameters):
|
|
|
203
213
|
except ZeroDivisionError:
|
|
204
214
|
return None
|
|
205
215
|
|
|
206
|
-
# @requires_array
|
|
207
216
|
def Median(s):
|
|
208
217
|
if isinstance(s[1], str):
|
|
209
218
|
return median([f(x, c) for x in f(s[1], c) if is_numeric(f(x, c))])
|
|
210
219
|
else:
|
|
211
220
|
return median([f(x, c) for x in s[1][1:] if is_numeric(f(x, c))])
|
|
212
221
|
|
|
213
|
-
# @requires_array
|
|
214
222
|
def Length(s):
|
|
215
223
|
if isinstance(s[1], str):
|
|
216
224
|
|
|
@@ -218,11 +226,9 @@ def create_mathjson_solver(solver_parameters):
|
|
|
218
226
|
else:
|
|
219
227
|
return len([x for x in s[1][1:]])
|
|
220
228
|
|
|
221
|
-
# @requires_array
|
|
222
229
|
def Any(s):
|
|
223
230
|
return any([f(x, c) for x in s[1][1:]])
|
|
224
231
|
|
|
225
|
-
# @requires_array
|
|
226
232
|
def All(s):
|
|
227
233
|
return all([f(x, c) for x in s[1][1:]])
|
|
228
234
|
|
|
@@ -397,6 +403,26 @@ def create_mathjson_solver(solver_parameters):
|
|
|
397
403
|
def TimeDeltaWeeks(s):
|
|
398
404
|
return datetime.timedelta(weeks=f(s[1], c))
|
|
399
405
|
|
|
406
|
+
# def Equal(s):
|
|
407
|
+
# a = comparison_safe_converter(f(s[1], c))
|
|
408
|
+
# b = comparison_safe_converter(f(s[2], c))
|
|
409
|
+
# return a == b
|
|
410
|
+
# if type(a) in [int, float, str]:
|
|
411
|
+
# a = f"{a}"
|
|
412
|
+
# elif type(a) in [bool, NoneType]:
|
|
413
|
+
# if a:
|
|
414
|
+
# a = True
|
|
415
|
+
# else:
|
|
416
|
+
# a = None
|
|
417
|
+
|
|
418
|
+
# if is_numeric(a):
|
|
419
|
+
|
|
420
|
+
# lambda s: f"{f(s[1], c)}" == f"{f(s[2], c)}",
|
|
421
|
+
|
|
422
|
+
def IsDefined(s):
|
|
423
|
+
# Todo: This does not work
|
|
424
|
+
return s[1] in c.keys()
|
|
425
|
+
|
|
400
426
|
constructs = {
|
|
401
427
|
"Sum": Sum,
|
|
402
428
|
"Add": Add,
|
|
@@ -419,7 +445,10 @@ def create_mathjson_solver(solver_parameters):
|
|
|
419
445
|
"Log": lambda s: math.log(f(s[1], c)),
|
|
420
446
|
"Log2": lambda s: math.log2(f(s[1], c)),
|
|
421
447
|
"Log10": lambda s: math.log10(f(s[1], c)),
|
|
422
|
-
"Equal": lambda s: f(s[1], c) == f(s[2], c),
|
|
448
|
+
# "Equal": lambda s: f"{f(s[1], c)}" == f"{f(s[2], c)}",
|
|
449
|
+
"Equal": lambda s: comparison_safe_converter(f(s[1], c))
|
|
450
|
+
== comparison_safe_converter(f(s[2], c)),
|
|
451
|
+
"StrictEqual": lambda s: f(s[1], c) == f(s[2], c),
|
|
423
452
|
"Greater": lambda s: f(s[1], c) > f(s[2], c),
|
|
424
453
|
"GreaterEqual": lambda s: f(s[1], c) >= f(s[2], c),
|
|
425
454
|
"Less": lambda s: f(s[1], c) < f(s[2], c),
|
|
@@ -452,7 +481,8 @@ def create_mathjson_solver(solver_parameters):
|
|
|
452
481
|
"Float": Float,
|
|
453
482
|
"Str": Str,
|
|
454
483
|
"Not": Not,
|
|
455
|
-
"IsDefined": lambda s: s[1] in c,
|
|
484
|
+
# "IsDefined": lambda s: s[1] in c,
|
|
485
|
+
"IsDefined": IsDefined,
|
|
456
486
|
"Map": Map,
|
|
457
487
|
"HasMatchingSublist": HasMatchingSublist,
|
|
458
488
|
"Strptime": Strptime,
|
|
@@ -467,7 +497,17 @@ def create_mathjson_solver(solver_parameters):
|
|
|
467
497
|
if s[0] in constructs:
|
|
468
498
|
try:
|
|
469
499
|
return constructs[s[0]](s)
|
|
470
|
-
|
|
500
|
+
|
|
501
|
+
# except RecursionError:
|
|
502
|
+
# return s[0]
|
|
503
|
+
# except Exception as e:
|
|
504
|
+
except TypeError as e:
|
|
505
|
+
raise MathJSONException(e, s, mathjson_construct=s[0])
|
|
506
|
+
except ValueError as e:
|
|
507
|
+
raise MathJSONException(e, s, mathjson_construct=s[0])
|
|
508
|
+
except IndexError as e:
|
|
509
|
+
raise MathJSONException(e, s, mathjson_construct=s[0])
|
|
510
|
+
except ZeroDivisionError as e:
|
|
471
511
|
raise MathJSONException(e, s, mathjson_construct=s[0])
|
|
472
512
|
else:
|
|
473
513
|
# raise MathJSONException(
|
|
@@ -475,7 +515,10 @@ def create_mathjson_solver(solver_parameters):
|
|
|
475
515
|
# )
|
|
476
516
|
return s
|
|
477
517
|
elif s in solver_parameters:
|
|
478
|
-
|
|
518
|
+
try:
|
|
519
|
+
return f(solver_parameters[s], c)
|
|
520
|
+
except RecursionError:
|
|
521
|
+
return solver_parameters[s]
|
|
479
522
|
elif s in c:
|
|
480
523
|
return f(c[s], c)
|
|
481
524
|
else:
|
|
@@ -536,6 +579,14 @@ def extract_variables(s: Union[list, int, float, str], li: set, ignore_list: set
|
|
|
536
579
|
"IsDefined",
|
|
537
580
|
"Map",
|
|
538
581
|
"HasMatchingSublist",
|
|
582
|
+
"Strptime",
|
|
583
|
+
"Strftime",
|
|
584
|
+
"Today",
|
|
585
|
+
"Now",
|
|
586
|
+
"TimeDeltaWeeks",
|
|
587
|
+
"TimeDeltaHours",
|
|
588
|
+
"TimeDeltaMinutes",
|
|
589
|
+
"TimeDeltaDays",
|
|
539
590
|
]
|
|
540
591
|
if isinstance(s, str):
|
|
541
592
|
if s in ignore_list:
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: mathjson-solver
|
|
3
|
+
Version: 1.12.0
|
|
4
|
+
Summary: Utilities for MathJSON evaluation
|
|
5
|
+
Home-page: https://github.com/LongenesisLtd/mathjson-solver
|
|
6
|
+
Author: Martins Mednis
|
|
7
|
+
Author-email: mrt@mednis.info
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/LongenesisLtd/mathjson-solver/issues
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.6
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Dynamic: author
|
|
16
|
+
Dynamic: author-email
|
|
17
|
+
Dynamic: classifier
|
|
18
|
+
Dynamic: description
|
|
19
|
+
Dynamic: description-content-type
|
|
20
|
+
Dynamic: home-page
|
|
21
|
+
Dynamic: project-url
|
|
22
|
+
Dynamic: requires-python
|
|
23
|
+
Dynamic: summary
|
|
24
|
+
|
|
25
|
+
# MathJSON Solver
|
|
26
|
+
|
|
27
|
+
[](https://pypi.org/project/mathjson-solver/)
|
|
28
|
+
[](https://pepy.tech/projects/mathjson-solver)
|
|
29
|
+

|
|
30
|
+
|
|
31
|
+
_MathJSON Solver_ is a Python module to numerically evaluate MathJSON expressions, like `["Add", 1, 2]`. It is developed by [Longenesis](https://longenesis.com/team) to enable numerical evaluation of user provided mathematical expressions in Longenesis digital health products. Its development was inspired by [CortexJS](https://cortexjs.io/compute-engine/) Compute Engine.
|
|
32
|
+
|
|
33
|
+
Please ask questions and share feedback in our Gitter chat [https://gitter.im/mathjson-solver/community](https://gitter.im/mathjson-solver/community).
|
|
34
|
+
[](https://gitter.im/mathjson-solver/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
|
35
|
+
|
|
36
|
+
## How to use
|
|
37
|
+
```python
|
|
38
|
+
from mathjson_solver import create_solver
|
|
39
|
+
|
|
40
|
+
parameters = {"x": 2, "y": 3}
|
|
41
|
+
expression = ["Add", "x", "y", 4]
|
|
42
|
+
|
|
43
|
+
solver = create_solver(parameters)
|
|
44
|
+
answer = solver(expression)
|
|
45
|
+
|
|
46
|
+
print(answer)
|
|
47
|
+
# 9, because 2+3+4=9
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Currently supported constructs
|
|
51
|
+
Find the full list of supported constructs in the [docs/README.md](https://github.com/LongenesisLtd/mathjson-solver/blob/main/docs/README.md).
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
## Exception handling
|
|
55
|
+
|
|
56
|
+
A `MathJSONException` is raised when expression cannot be evaluated. Import `MathJSONException` to handle it:
|
|
57
|
+
```python
|
|
58
|
+
from mathjson_solver import create_solver, MathJSONException
|
|
59
|
+
|
|
60
|
+
solver = create_solver({})
|
|
61
|
+
try:
|
|
62
|
+
solver(["Divide", 1, 0])
|
|
63
|
+
except MathJSONException:
|
|
64
|
+
pass
|
|
65
|
+
# invoke your own exception logger here
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Left unhandled, the exception will look like `MathJSONException("Problem in Divide. ['Divide', 1, 0]. division by zero")`.
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## How to run tests
|
|
72
|
+
Make sure you have `pytest` installed. Then `cd` into project directory and run:
|
|
73
|
+
```bash
|
|
74
|
+
pytest
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Contributing Code
|
|
78
|
+
|
|
79
|
+
We welcome your contributions in the form of pull requests.
|
|
80
|
+
|
|
81
|
+
1. Fork the repo;
|
|
82
|
+
2. Make improvements;
|
|
83
|
+
3. Make a pull request to share your improvements with the community and to include it into official release.
|