mathai 0.4.0__py3-none-any.whl → 0.6.9__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.
- mathai/__init__.py +18 -11
- mathai/apart.py +41 -12
- mathai/base.py +141 -38
- mathai/bivariate_inequality.py +317 -0
- mathai/diff.py +3 -3
- mathai/expand.py +92 -93
- mathai/factor.py +213 -41
- mathai/fraction.py +2 -2
- mathai/integrate.py +96 -34
- mathai/inverse.py +4 -4
- mathai/limit.py +96 -70
- mathai/linear.py +96 -84
- mathai/logic.py +7 -1
- mathai/matrix.py +228 -0
- mathai/ode.py +124 -0
- mathai/parser.py +13 -7
- mathai/parsetab.py +61 -0
- mathai/printeq.py +12 -9
- mathai/simplify.py +511 -333
- mathai/structure.py +2 -2
- mathai/tool.py +105 -4
- mathai/trig.py +134 -72
- mathai/univariate_inequality.py +78 -30
- {mathai-0.4.0.dist-info → mathai-0.6.9.dist-info}/METADATA +4 -1
- mathai-0.6.9.dist-info/RECORD +28 -0
- {mathai-0.4.0.dist-info → mathai-0.6.9.dist-info}/WHEEL +1 -1
- mathai/search.py +0 -117
- mathai-0.4.0.dist-info/RECORD +0 -25
- {mathai-0.4.0.dist-info → mathai-0.6.9.dist-info}/top_level.txt +0 -0
mathai/matrix.py
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
from .base import *
|
|
2
|
+
import copy
|
|
3
|
+
from .simplify import simplify
|
|
4
|
+
import itertools
|
|
5
|
+
|
|
6
|
+
# ---------- tree <-> python list ----------
|
|
7
|
+
def tree_to_py(node):
|
|
8
|
+
if node.name=="f_list":
|
|
9
|
+
return [tree_to_py(c) for c in node.children]
|
|
10
|
+
return node
|
|
11
|
+
|
|
12
|
+
def py_to_tree(obj):
|
|
13
|
+
if isinstance(obj,list):
|
|
14
|
+
return TreeNode("f_list",[py_to_tree(x) for x in obj])
|
|
15
|
+
return obj
|
|
16
|
+
|
|
17
|
+
# ---------- shape detection ----------
|
|
18
|
+
def is_vector(x):
|
|
19
|
+
return isinstance(x,list) and all(isinstance(item,TreeNode) for item in x)
|
|
20
|
+
def is_mat(x):
|
|
21
|
+
return isinstance(x,list) and all(isinstance(item,list) for item in x)
|
|
22
|
+
def is_matrix(x):
|
|
23
|
+
return isinstance(x, list) and all(isinstance(item, list) and (is_mat(item) or is_vector(item)) for item in x)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ---------- algebra primitives ----------
|
|
27
|
+
def dot(u,v):
|
|
28
|
+
if len(u)!=len(v):
|
|
29
|
+
raise ValueError("Vector size mismatch")
|
|
30
|
+
s = tree_form("d_0")
|
|
31
|
+
for a,b in zip(u,v):
|
|
32
|
+
s = TreeNode("f_add",[s,TreeNode("f_mul",[a,b])])
|
|
33
|
+
return s
|
|
34
|
+
|
|
35
|
+
def matmul(A, B):
|
|
36
|
+
# A: n × m
|
|
37
|
+
# B: m × p
|
|
38
|
+
|
|
39
|
+
n = len(A)
|
|
40
|
+
m = len(A[0])
|
|
41
|
+
p = len(B[0])
|
|
42
|
+
|
|
43
|
+
if m != len(B):
|
|
44
|
+
raise ValueError("Matrix dimension mismatch")
|
|
45
|
+
|
|
46
|
+
C = [[tree_form("d_0") for _ in range(p)] for _ in range(n)]
|
|
47
|
+
|
|
48
|
+
for i in range(n):
|
|
49
|
+
for j in range(p):
|
|
50
|
+
for k in range(m):
|
|
51
|
+
C[i][j] = TreeNode(
|
|
52
|
+
"f_add",
|
|
53
|
+
[C[i][j], TreeNode("f_mul", [A[i][k], B[k][j]])]
|
|
54
|
+
)
|
|
55
|
+
return C
|
|
56
|
+
|
|
57
|
+
# ---------- promotion ----------
|
|
58
|
+
def promote(node):
|
|
59
|
+
if node.name=="f_list":
|
|
60
|
+
return tree_to_py(node)
|
|
61
|
+
return node
|
|
62
|
+
def contains_neg(node):
|
|
63
|
+
if isinstance(node, list):
|
|
64
|
+
return False
|
|
65
|
+
if node.name.startswith("v_-"):
|
|
66
|
+
return False
|
|
67
|
+
for child in node.children:
|
|
68
|
+
if not contains_neg(child):
|
|
69
|
+
return False
|
|
70
|
+
return True
|
|
71
|
+
# ---------- multiplication (fully simplified) ----------
|
|
72
|
+
def multiply(left,right):
|
|
73
|
+
if left == tree_form("d_1"):
|
|
74
|
+
return right
|
|
75
|
+
if right == tree_form("d_1"):
|
|
76
|
+
return left
|
|
77
|
+
left2, right2 = left, right
|
|
78
|
+
if left2.name != "f_pow":
|
|
79
|
+
left2 = left2 ** 1
|
|
80
|
+
if right2.name != "f_pow":
|
|
81
|
+
right2 = right2 ** 1
|
|
82
|
+
if left2.name == "f_pow" and right2.name == "f_pow" and left2.children[0]==right2.children[0]:
|
|
83
|
+
return simplify(left2.children[0]**(left2.children[1]+right2.children[1]))
|
|
84
|
+
A,B = promote(left), promote(right)
|
|
85
|
+
|
|
86
|
+
# vector · vector
|
|
87
|
+
if is_vector(A) and is_vector(B):
|
|
88
|
+
return dot(A,B)
|
|
89
|
+
# matrix × matrix
|
|
90
|
+
if is_matrix(A) and is_matrix(B):
|
|
91
|
+
return py_to_tree(matmul(A,B))
|
|
92
|
+
# scalar × vector
|
|
93
|
+
for _ in range(2):
|
|
94
|
+
if contains_neg(A) and is_vector(B):
|
|
95
|
+
return py_to_tree([TreeNode("f_mul",[A,x]) for x in B])
|
|
96
|
+
# scalar × matrix
|
|
97
|
+
if contains_neg(A) and is_matrix(B):
|
|
98
|
+
return py_to_tree([[TreeNode("f_mul",[A,x]) for x in row] for row in B])
|
|
99
|
+
A, B = B, A
|
|
100
|
+
return None
|
|
101
|
+
def add_vec(A, B):
|
|
102
|
+
if len(A) != len(B):
|
|
103
|
+
raise ValueError("Vector dimension mismatch")
|
|
104
|
+
|
|
105
|
+
return [
|
|
106
|
+
TreeNode("f_add", [A[i], B[i]])
|
|
107
|
+
for i in range(len(A))
|
|
108
|
+
]
|
|
109
|
+
def matadd(A, B):
|
|
110
|
+
if len(A) != len(B) or len(A[0]) != len(B[0]):
|
|
111
|
+
raise ValueError("Matrix dimension mismatch")
|
|
112
|
+
|
|
113
|
+
n = len(A)
|
|
114
|
+
m = len(A[0])
|
|
115
|
+
|
|
116
|
+
return [
|
|
117
|
+
[
|
|
118
|
+
TreeNode("f_add", [A[i][j], B[i][j]])
|
|
119
|
+
for j in range(m)
|
|
120
|
+
]
|
|
121
|
+
for i in range(n)
|
|
122
|
+
]
|
|
123
|
+
def addition(left,right):
|
|
124
|
+
A,B = promote(left), promote(right)
|
|
125
|
+
# vector + vector
|
|
126
|
+
if is_vector(A) and is_vector(B):
|
|
127
|
+
return add_vec(A,B)
|
|
128
|
+
# matrix + matrix
|
|
129
|
+
if is_matrix(A) and is_matrix(B):
|
|
130
|
+
return py_to_tree(matadd(A,B))
|
|
131
|
+
return None
|
|
132
|
+
'''
|
|
133
|
+
def fold_wmul(eq):
|
|
134
|
+
if eq.name == "f_pow" and eq.children[1].name.startswith("d_"):
|
|
135
|
+
n = int(eq.children[1].name[2:])
|
|
136
|
+
if n == 1:
|
|
137
|
+
eq = eq.children[0]
|
|
138
|
+
elif n > 1:
|
|
139
|
+
tmp = promote(eq.children[0])
|
|
140
|
+
if is_matrix(tmp):
|
|
141
|
+
orig =tmp
|
|
142
|
+
for i in range(n-1):
|
|
143
|
+
tmp = matmul(orig, tmp)
|
|
144
|
+
eq = py_to_tree(tmp)
|
|
145
|
+
elif eq.name in ["f_wmul", "f_add"]:
|
|
146
|
+
if len(eq.children) == 1:
|
|
147
|
+
eq = eq.children[0]
|
|
148
|
+
else:
|
|
149
|
+
i = len(eq.children)-1
|
|
150
|
+
while i>0:
|
|
151
|
+
if eq.name == "f_wmul":
|
|
152
|
+
out = multiply(eq.children[i-1], eq.children[i])
|
|
153
|
+
else:
|
|
154
|
+
out = addition(eq.children[i-1], eq.children[i])
|
|
155
|
+
if out is not None:
|
|
156
|
+
eq.children.pop(i)
|
|
157
|
+
eq.children.pop(i-1)
|
|
158
|
+
eq.children.insert(i-1,out)
|
|
159
|
+
i = i-1
|
|
160
|
+
return TreeNode(eq.name, [fold_wmul(child) for child in eq.children])
|
|
161
|
+
'''
|
|
162
|
+
def fold_wmul(root):
|
|
163
|
+
# Post-order traversal using explicit stack
|
|
164
|
+
stack = [(root, False)]
|
|
165
|
+
newnode = {}
|
|
166
|
+
|
|
167
|
+
while stack:
|
|
168
|
+
node, visited = stack.pop()
|
|
169
|
+
|
|
170
|
+
if not visited:
|
|
171
|
+
# First time: push back as visited, then children
|
|
172
|
+
stack.append((node, True))
|
|
173
|
+
for child in node.children:
|
|
174
|
+
stack.append((child, False))
|
|
175
|
+
else:
|
|
176
|
+
# All children already processed
|
|
177
|
+
children = [newnode[c] for c in node.children]
|
|
178
|
+
eq = TreeNode(node.name, children)
|
|
179
|
+
|
|
180
|
+
# ---- original rewrite logic ----
|
|
181
|
+
|
|
182
|
+
if eq.name == "f_pow" and eq.children[1].name.startswith("d_"):
|
|
183
|
+
n = int(eq.children[1].name[2:])
|
|
184
|
+
if n == 1:
|
|
185
|
+
eq = eq.children[0]
|
|
186
|
+
elif n > 1:
|
|
187
|
+
tmp = promote(eq.children[0])
|
|
188
|
+
if is_matrix(tmp):
|
|
189
|
+
orig = tmp
|
|
190
|
+
for _ in range(n - 1):
|
|
191
|
+
tmp = matmul(orig, tmp)
|
|
192
|
+
eq = py_to_tree(tmp)
|
|
193
|
+
|
|
194
|
+
elif eq.name in ["f_wmul", "f_add"]:
|
|
195
|
+
if len(eq.children) == 1:
|
|
196
|
+
eq = eq.children[0]
|
|
197
|
+
else:
|
|
198
|
+
i = len(eq.children) - 1
|
|
199
|
+
while i > 0:
|
|
200
|
+
if eq.name == "f_wmul":
|
|
201
|
+
out = multiply(eq.children[i - 1], eq.children[i])
|
|
202
|
+
else:
|
|
203
|
+
out = addition(eq.children[i - 1], eq.children[i])
|
|
204
|
+
|
|
205
|
+
if out is not None:
|
|
206
|
+
eq.children.pop(i)
|
|
207
|
+
eq.children.pop(i - 1)
|
|
208
|
+
eq.children.insert(i - 1, out)
|
|
209
|
+
i -= 1
|
|
210
|
+
|
|
211
|
+
# --------------------------------
|
|
212
|
+
|
|
213
|
+
newnode[node] = eq
|
|
214
|
+
|
|
215
|
+
return newnode[root]
|
|
216
|
+
|
|
217
|
+
def flat(eq):
|
|
218
|
+
return flatten_tree(eq, ["f_wmul"])
|
|
219
|
+
def use(eq):
|
|
220
|
+
return TreeNode(eq.name, [use(child) for child in eq.children])
|
|
221
|
+
def _matrix_solve(eq):
|
|
222
|
+
if TreeNode.matmul == True:
|
|
223
|
+
TreeNode.matmul = False
|
|
224
|
+
eq = dowhile(eq, lambda x: fold_wmul(use(flat(x))))
|
|
225
|
+
TreeNode.matmul = True
|
|
226
|
+
return eq
|
|
227
|
+
def matrix_solve(eq):
|
|
228
|
+
return _matrix_solve(eq)
|
mathai/ode.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
from .factor import factor
|
|
2
|
+
from .expand import expand
|
|
3
|
+
from .base import *
|
|
4
|
+
from .fraction import fraction
|
|
5
|
+
from .simplify import simplify
|
|
6
|
+
import copy
|
|
7
|
+
|
|
8
|
+
def inversediff(lhs, rhs):
|
|
9
|
+
count = 4
|
|
10
|
+
while contain(rhs, tree_form("v_1")) or contain(lhs, tree_form("v_0")):
|
|
11
|
+
success = False
|
|
12
|
+
if rhs.name == "f_add":
|
|
13
|
+
for i in range(len(rhs.children)-1,-1,-1):
|
|
14
|
+
if not contain(rhs.children[i], tree_form("v_0")) or str_form(tree_form("v_1").fx("dif")) in [str_form(x) for x in factor_generation(rhs.children[i])]:
|
|
15
|
+
if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
|
|
16
|
+
success = True
|
|
17
|
+
lhs = lhs - rhs.children[i]
|
|
18
|
+
rhs.children.pop(i)
|
|
19
|
+
elif rhs.name == "f_mul":
|
|
20
|
+
for i in range(len(rhs.children)-1,-1,-1):
|
|
21
|
+
if not contain(rhs.children[i], tree_form("v_0")):
|
|
22
|
+
if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
|
|
23
|
+
success = True
|
|
24
|
+
lhs = lhs / rhs.children[i]
|
|
25
|
+
rhs.children.pop(i)
|
|
26
|
+
if len(rhs.children) == 1:
|
|
27
|
+
rhs = rhs.children[0]
|
|
28
|
+
rhs, lhs = copy.deepcopy([simplify(lhs), simplify(rhs)])
|
|
29
|
+
if rhs.name == "f_add":
|
|
30
|
+
for i in range(len(rhs.children)-1,-1,-1):
|
|
31
|
+
if not contain(rhs.children[i], tree_form("v_1")) or str_form(tree_form("v_0").fx("dif")) in [str_form(x) for x in factor_generation(rhs.children[i])]:
|
|
32
|
+
if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
|
|
33
|
+
success = True
|
|
34
|
+
lhs = lhs - rhs.children[i]
|
|
35
|
+
rhs.children.pop(i)
|
|
36
|
+
elif rhs.name == "f_mul":
|
|
37
|
+
for i in range(len(rhs.children)-1,-1,-1):
|
|
38
|
+
if not contain(rhs.children[i], tree_form("v_1")):
|
|
39
|
+
if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
|
|
40
|
+
success = True
|
|
41
|
+
lhs = lhs / rhs.children[i]
|
|
42
|
+
rhs.children.pop(i)
|
|
43
|
+
rhs, lhs = copy.deepcopy([simplify(lhs), simplify(rhs)])
|
|
44
|
+
if not success:
|
|
45
|
+
lhs, rhs = factor(lhs),factor(rhs)
|
|
46
|
+
count -= 1
|
|
47
|
+
if count == 0:
|
|
48
|
+
return simplify(e0(lhs-rhs))
|
|
49
|
+
return simplify(e0(lhs-rhs))
|
|
50
|
+
|
|
51
|
+
intconst = ["v_"+str(i) for i in range(101,150)]
|
|
52
|
+
def allocvar():
|
|
53
|
+
global intconst
|
|
54
|
+
return tree_form(intconst.pop(0))
|
|
55
|
+
|
|
56
|
+
def epowersplit(eq):
|
|
57
|
+
if eq.name == "f_pow" and eq.children[1].name == "f_add":
|
|
58
|
+
return product([eq.children[0]**child for child in eq.children[1].children])
|
|
59
|
+
return TreeNode(eq.name, [epowersplit(child) for child in eq.children])
|
|
60
|
+
def esolve(s):
|
|
61
|
+
if s.name == "f_add" and "f_log" in str_form(s):
|
|
62
|
+
return product([tree_form("s_e")**child for child in s.children]) - tree_form("d_1")
|
|
63
|
+
return TreeNode(s.name, [esolve(child) for child in s.children])
|
|
64
|
+
def diffsolve_sep2(eq):
|
|
65
|
+
global tab
|
|
66
|
+
|
|
67
|
+
s = []
|
|
68
|
+
eq = simplify(expand(eq))
|
|
69
|
+
eq = e1(eq)
|
|
70
|
+
|
|
71
|
+
def vlor1(eq):
|
|
72
|
+
if contain(eq, tree_form("v_0")) and not contain(eq, tree_form("v_1")):
|
|
73
|
+
return True
|
|
74
|
+
if contain(eq, tree_form("v_1")) and not contain(eq, tree_form("v_0")):
|
|
75
|
+
return True
|
|
76
|
+
return False
|
|
77
|
+
if eq.name == "f_add" and all(vlor1(child) and [str_form(x) for x in factor_generation(copy.deepcopy(child))].count(str_form(tree_form(vlist(child)[0]).fx("dif")))==1 for child in eq.children):
|
|
78
|
+
for child in eq.children:
|
|
79
|
+
v = vlist(child)[0]
|
|
80
|
+
v2 = tree_form(v).fx("dif")
|
|
81
|
+
child = replace(child, v2, tree_form("d_1"))
|
|
82
|
+
child = simplify(child)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
tmp6 = TreeNode("f_integrate", [child, tree_form(v)])
|
|
86
|
+
s.append(tmp6)
|
|
87
|
+
|
|
88
|
+
if s[-1] is None:
|
|
89
|
+
return None
|
|
90
|
+
s.append(allocvar())
|
|
91
|
+
else:
|
|
92
|
+
return None
|
|
93
|
+
s = summation(s)
|
|
94
|
+
s = simplify(e0(s))
|
|
95
|
+
|
|
96
|
+
return groupe(s)
|
|
97
|
+
def e0(eq):
|
|
98
|
+
return TreeNode("f_eq", [eq, tree_form("d_0")])
|
|
99
|
+
def e1(eq):
|
|
100
|
+
if eq.name == "f_eq":
|
|
101
|
+
eq = eq.children[0]
|
|
102
|
+
return eq
|
|
103
|
+
def groupe(eq):
|
|
104
|
+
eq = esolve(eq)
|
|
105
|
+
eq = simplify(eq)
|
|
106
|
+
eq = fraction(eq)
|
|
107
|
+
eq = simplify(eq)
|
|
108
|
+
eq = epowersplit(eq)
|
|
109
|
+
return eq
|
|
110
|
+
|
|
111
|
+
def diffsolve_sep(eq):
|
|
112
|
+
eq = epowersplit(eq)
|
|
113
|
+
|
|
114
|
+
eq = inversediff(tree_form("d_0"), eq.children[0].copy_tree())
|
|
115
|
+
return eq
|
|
116
|
+
|
|
117
|
+
def diffsolve(eq):
|
|
118
|
+
orig = eq.copy_tree()
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
eq = diffsolve_sep2(eq)
|
|
122
|
+
if eq is None:
|
|
123
|
+
return orig
|
|
124
|
+
return eq
|
mathai/parser.py
CHANGED
|
@@ -37,7 +37,7 @@ grammar = """
|
|
|
37
37
|
| arithmetic "-" term -> sub
|
|
38
38
|
| term
|
|
39
39
|
|
|
40
|
-
?term: term "*" power ->
|
|
40
|
+
?term: term "*" power -> wmul
|
|
41
41
|
| term "/" power -> div
|
|
42
42
|
| term "." power -> dot
|
|
43
43
|
| power
|
|
@@ -59,7 +59,7 @@ grammar = """
|
|
|
59
59
|
| ESCAPED_STRING -> string
|
|
60
60
|
| CAPITAL_ID -> matrix
|
|
61
61
|
|
|
62
|
-
FUNC_NAME: "midpoint" | "ref" | "subs" | "try" | "forall" | "imply" | "exist" | "len" | "sum" | "angle" | "line" | "sum2" | "charge" | "electricfield" | "perm" | "point" | "equationrhs" | "transpose" | "equationlhs" | "equation" | "error" | "covariance" | "variance" | "expect" | "mag" | "rad" | "laplace" | "diverge" | "pdif" | "gradient" | "curl" | "point1" | "point2" | "dot" | "point3" | "line1" | "line2" | "line3" | "sin" | "circumcenter" | "eqtri" | "linesegment" | "cos" | "tan" | "log" | "sqrt" | "integrate" | "dif" | "abs" | "cosec" | "sec" | "cot" | "arctan" | "arcsin" | "arccos" | "log10"
|
|
62
|
+
FUNC_NAME: "midpoint" | "ref" | "subs" | "try" | "limit" | "forall" | "limitpinf" | "imply" | "exist" | "len" | "sum" | "angle" | "line" | "sum2" | "charge" | "electricfield" | "perm" | "point" | "equationrhs" | "transpose" | "equationlhs" | "equation" | "error" | "covariance" | "variance" | "expect" | "mag" | "rad" | "laplace" | "diverge" | "pdif" | "gradient" | "curl" | "point1" | "point2" | "dot" | "point3" | "line1" | "line2" | "line3" | "sin" | "circumcenter" | "eqtri" | "linesegment" | "cos" | "tan" | "log" | "sqrt" | "integrate" | "dif" | "abs" | "cosec" | "sec" | "cot" | "arctan" | "arcsin" | "arccos" | "log10"
|
|
63
63
|
|
|
64
64
|
VARIABLE: /[a-z]/ | "nabla" | "pi" | "kc" | "hbar" | "em" | "ec" | "anot" | "false" | "true"
|
|
65
65
|
|
|
@@ -85,7 +85,7 @@ def parse(equation, funclist=None):
|
|
|
85
85
|
|
|
86
86
|
parser_main = Lark(grammar2, start='start', parser='lalr')
|
|
87
87
|
parse_tree = parser_main.parse(equation)
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
# Convert Lark tree to TreeNode
|
|
90
90
|
def convert_to_treenode(parse_tree):
|
|
91
91
|
if isinstance(parse_tree, Tree):
|
|
@@ -130,7 +130,7 @@ def parse(equation, funclist=None):
|
|
|
130
130
|
if tree_node.name == "pass_through":
|
|
131
131
|
return fxchange(tree_node.children[0])
|
|
132
132
|
return TreeNode(
|
|
133
|
-
"f_" + tree_node.name if tree_node.name in tmp3 + ["try", "ref", "sqrt","imply","forall","exist","exclude","union","intersection","len","index","angle","charge","sum2","electricfield","line","point","sum","transpose","equationrhs","equationlhs","equation","covariance","variance","expect","error","laplace","dot","curl","pdif","diverge","gradient","rad","ge","le","gt","lt","eqtri","linesegment","midpoint","mag","point1","point2","point3","line1","line2","line3","log10","arcsin","arccos","arctan","list","cosec","sec","cot","equiv","or","not","and","circumcenter","eq","sub","add","sin","cos","tan","
|
|
133
|
+
"f_" + tree_node.name if tree_node.name in tmp3 + ["limitpinf", "limit", "try", "ref", "sqrt","imply","forall","exist","exclude","union","intersection","len","index","angle","charge","sum2","electricfield","line","point","sum","transpose","equationrhs","equationlhs","equation","covariance","variance","expect","error","laplace","dot","curl","pdif","diverge","gradient","rad","ge","le","gt","lt","eqtri","linesegment","midpoint","mag","point1","point2","point3","line1","line2","line3","log10","arcsin","arccos","arctan","list","cosec","sec","cot","equiv","or","not","and","circumcenter","eq","sub","add","sin","cos","tan","wmul","integrate","dif","pow","div","log","abs"] else "d_" + tree_node.name,
|
|
134
134
|
[fxchange(child) for child in tree_node.children]
|
|
135
135
|
)
|
|
136
136
|
|
|
@@ -146,13 +146,19 @@ def parse(equation, funclist=None):
|
|
|
146
146
|
for i, c in enumerate([chr(x+ord("A")) for x in range(0,26)]):
|
|
147
147
|
tree_node = replace(tree_node, tree_form("d_"+c), tree_form("v_-"+str(i+1)))
|
|
148
148
|
tree_node = replace(tree_node, tree_form("f_"+c), tree_form("v_-"+str(i+1)))
|
|
149
|
-
|
|
150
|
-
# Final recursive replacements
|
|
149
|
+
|
|
151
150
|
def rfx(tree_node):
|
|
152
151
|
if tree_node.name[:3] == "d_c":
|
|
153
152
|
return tree_form("v_" + str(int(tree_node.name[3:])+100))
|
|
154
153
|
tree_node.children = [rfx(child) for child in tree_node.children]
|
|
155
154
|
return tree_node
|
|
156
|
-
|
|
155
|
+
|
|
157
156
|
tree_node = rfx(tree_node)
|
|
157
|
+
tree_node = flatten_tree(tree_node, ["f_wmul"])
|
|
158
|
+
if TreeNode.matmul == True:
|
|
159
|
+
TreeNode.matmul = False
|
|
160
|
+
tree_node = use(tree_form(str_form(tree_node).replace("f_w","f_")))
|
|
161
|
+
TreeNode.matmul = True
|
|
162
|
+
else:
|
|
163
|
+
tree_node = tree_form(str_form(tree_node).replace("f_w","f_"))
|
|
158
164
|
return tree_node
|
mathai/parsetab.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
|
|
2
|
+
# parsetab.py
|
|
3
|
+
# This file is automatically generated. Do not edit.
|
|
4
|
+
# pylint: disable=W,C,R
|
|
5
|
+
_tabversion = '3.10'
|
|
6
|
+
|
|
7
|
+
_lr_method = 'LALR'
|
|
8
|
+
|
|
9
|
+
_lr_signature = 'leftEQUIVleftIMPLYleftORleftANDleftEQLTGTLEGEleftPLUSMINUSleftTIMESDIVDOTrightPOWrightNOTUMINUSUPLUSAND CAPITAL_ID CNUMBER COMMA DIV DOT EQ EQUIV GE GT IMPLY LBRACK LE LPAREN LT MINUS NOT NUMBER OR PLUS POW RBRACK RPAREN STRING TIMES VARIABLEstart : exprexpr : expr EQUIV exprexpr : expr IMPLY exprexpr : expr OR exprexpr : expr AND exprexpr : NOT exprexpr : expr EQ expr\n | expr LT expr\n | expr GT expr\n | expr LE expr\n | expr GE exprexpr : expr PLUS expr\n | expr MINUS exprexpr : expr TIMES expr\n | expr DIV expr\n | expr DOT exprexpr : expr POW exprexpr : MINUS expr %prec UMINUSexpr : PLUS expr %prec UPLUSexpr : atomexpr : LPAREN expr RPARENexpr : LBRACK expr_list RBRACKexpr : LBRACK RBRACKexpr_list : expr_list COMMA exprexpr_list : exprexpr : VARIABLE LPAREN expr_list RPARENatom : VARIABLE\n | CAPITAL_ID\n | NUMBER\n | CNUMBER\n | STRING'
|
|
10
|
+
|
|
11
|
+
_lr_action_items = {'NOT':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,]),'MINUS':([0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,56,57,],[5,24,5,5,5,-20,5,5,-27,-28,-29,-30,-31,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,-6,-19,-18,24,-23,24,5,24,24,24,24,24,24,24,24,24,-12,-13,-14,-15,-16,-17,-21,-22,5,24,-26,]),'PLUS':([0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,56,57,],[4,23,4,4,4,-20,4,4,-27,-28,-29,-30,-31,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,-6,-19,-18,23,-23,23,4,23,23,23,23,23,23,23,23,23,-12,-13,-14,-15,-16,-17,-21,-22,4,23,-26,]),'LPAREN':([0,3,4,5,7,8,9,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[7,7,7,7,7,7,36,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'LBRACK':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,]),'VARIABLE':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,]),'CAPITAL_ID':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,]),'NUMBER':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,]),'CNUMBER':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,]),'STRING':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,]),'$end':([1,2,6,9,10,11,12,13,29,30,31,34,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,57,],[0,-1,-20,-27,-28,-29,-30,-31,-6,-19,-18,-23,-2,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,-26,]),'EQUIV':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[14,-20,-27,-28,-29,-30,-31,-6,-19,-18,14,-23,14,-2,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,14,-26,]),'IMPLY':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[15,-20,-27,-28,-29,-30,-31,-6,-19,-18,15,-23,15,15,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,15,-26,]),'OR':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[16,-20,-27,-28,-29,-30,-31,-6,-19,-18,16,-23,16,16,16,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,16,-26,]),'AND':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[17,-20,-27,-28,-29,-30,-31,-6,-19,-18,17,-23,17,17,17,17,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,17,-26,]),'EQ':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[18,-20,-27,-28,-29,-30,-31,-6,-19,-18,18,-23,18,18,18,18,18,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,18,-26,]),'LT':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[19,-20,-27,-28,-29,-30,-31,-6,-19,-18,19,-23,19,19,19,19,19,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,19,-26,]),'GT':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[20,-20,-27,-28,-29,-30,-31,-6,-19,-18,20,-23,20,20,20,20,20,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,20,-26,]),'LE':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[21,-20,-27,-28,-29,-30,-31,-6,-19,-18,21,-23,21,21,21,21,21,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,21,-26,]),'GE':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[22,-20,-27,-28,-29,-30,-31,-6,-19,-18,22,-23,22,22,22,22,22,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,22,-26,]),'TIMES':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[25,-20,-27,-28,-29,-30,-31,-6,-19,-18,25,-23,25,25,25,25,25,25,25,25,25,25,25,25,-14,-15,-16,-17,-21,-22,25,-26,]),'DIV':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[26,-20,-27,-28,-29,-30,-31,-6,-19,-18,26,-23,26,26,26,26,26,26,26,26,26,26,26,26,-14,-15,-16,-17,-21,-22,26,-26,]),'DOT':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[27,-20,-27,-28,-29,-30,-31,-6,-19,-18,27,-23,27,27,27,27,27,27,27,27,27,27,27,27,-14,-15,-16,-17,-21,-22,27,-26,]),'POW':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[28,-20,-27,-28,-29,-30,-31,-6,-19,-18,28,-23,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,-21,-22,28,-26,]),'RPAREN':([6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,56,57,],[-20,-27,-28,-29,-30,-31,-6,-19,-18,52,-23,-25,-2,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,57,-24,-26,]),'RBRACK':([6,8,9,10,11,12,13,29,30,31,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[-20,34,-27,-28,-29,-30,-31,-6,-19,-18,53,-23,-25,-2,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,-24,-26,]),'COMMA':([6,9,10,11,12,13,29,30,31,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,56,57,],[-20,-27,-28,-29,-30,-31,-6,-19,-18,54,-23,-25,-2,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,54,-24,-26,]),}
|
|
12
|
+
|
|
13
|
+
_lr_action = {}
|
|
14
|
+
for _k, _v in _lr_action_items.items():
|
|
15
|
+
for _x,_y in zip(_v[0],_v[1]):
|
|
16
|
+
if not _x in _lr_action: _lr_action[_x] = {}
|
|
17
|
+
_lr_action[_x][_k] = _y
|
|
18
|
+
del _lr_action_items
|
|
19
|
+
|
|
20
|
+
_lr_goto_items = {'start':([0,],[1,]),'expr':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[2,29,30,31,32,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,35,56,]),'atom':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,]),'expr_list':([8,36,],[33,55,]),}
|
|
21
|
+
|
|
22
|
+
_lr_goto = {}
|
|
23
|
+
for _k, _v in _lr_goto_items.items():
|
|
24
|
+
for _x, _y in zip(_v[0], _v[1]):
|
|
25
|
+
if not _x in _lr_goto: _lr_goto[_x] = {}
|
|
26
|
+
_lr_goto[_x][_k] = _y
|
|
27
|
+
del _lr_goto_items
|
|
28
|
+
_lr_productions = [
|
|
29
|
+
("S' -> start","S'",1,None,None,None),
|
|
30
|
+
('start -> expr','start',1,'p_start','parser.py',98),
|
|
31
|
+
('expr -> expr EQUIV expr','expr',3,'p_expr_equiv','parser.py',105),
|
|
32
|
+
('expr -> expr IMPLY expr','expr',3,'p_expr_imply','parser.py',109),
|
|
33
|
+
('expr -> expr OR expr','expr',3,'p_expr_or','parser.py',113),
|
|
34
|
+
('expr -> expr AND expr','expr',3,'p_expr_and','parser.py',117),
|
|
35
|
+
('expr -> NOT expr','expr',2,'p_expr_not','parser.py',121),
|
|
36
|
+
('expr -> expr EQ expr','expr',3,'p_expr_cmp','parser.py',128),
|
|
37
|
+
('expr -> expr LT expr','expr',3,'p_expr_cmp','parser.py',129),
|
|
38
|
+
('expr -> expr GT expr','expr',3,'p_expr_cmp','parser.py',130),
|
|
39
|
+
('expr -> expr LE expr','expr',3,'p_expr_cmp','parser.py',131),
|
|
40
|
+
('expr -> expr GE expr','expr',3,'p_expr_cmp','parser.py',132),
|
|
41
|
+
('expr -> expr PLUS expr','expr',3,'p_expr_add','parser.py',146),
|
|
42
|
+
('expr -> expr MINUS expr','expr',3,'p_expr_add','parser.py',147),
|
|
43
|
+
('expr -> expr TIMES expr','expr',3,'p_expr_mul','parser.py',154),
|
|
44
|
+
('expr -> expr DIV expr','expr',3,'p_expr_mul','parser.py',155),
|
|
45
|
+
('expr -> expr DOT expr','expr',3,'p_expr_mul','parser.py',156),
|
|
46
|
+
('expr -> expr POW expr','expr',3,'p_expr_pow','parser.py',165),
|
|
47
|
+
('expr -> MINUS expr','expr',2,'p_expr_uminus','parser.py',172),
|
|
48
|
+
('expr -> PLUS expr','expr',2,'p_expr_uplus','parser.py',176),
|
|
49
|
+
('expr -> atom','expr',1,'p_expr_atom','parser.py',183),
|
|
50
|
+
('expr -> LPAREN expr RPAREN','expr',3,'p_expr_paren','parser.py',187),
|
|
51
|
+
('expr -> LBRACK expr_list RBRACK','expr',3,'p_expr_list','parser.py',191),
|
|
52
|
+
('expr -> LBRACK RBRACK','expr',2,'p_expr_list_single','parser.py',195),
|
|
53
|
+
('expr_list -> expr_list COMMA expr','expr_list',3,'p_expr_list_list','parser.py',199),
|
|
54
|
+
('expr_list -> expr','expr_list',1,'p_expr_list_item','parser.py',203),
|
|
55
|
+
('expr -> VARIABLE LPAREN expr_list RPAREN','expr',4,'p_expr_func','parser.py',207),
|
|
56
|
+
('atom -> VARIABLE','atom',1,'p_atom_var','parser.py',214),
|
|
57
|
+
('atom -> CAPITAL_ID','atom',1,'p_atom_var','parser.py',215),
|
|
58
|
+
('atom -> NUMBER','atom',1,'p_atom_var','parser.py',216),
|
|
59
|
+
('atom -> CNUMBER','atom',1,'p_atom_var','parser.py',217),
|
|
60
|
+
('atom -> STRING','atom',1,'p_atom_var','parser.py',218),
|
|
61
|
+
]
|
mathai/printeq.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from .base import *
|
|
2
|
-
from .
|
|
2
|
+
from .factor import merge_sqrt
|
|
3
|
+
from .simplify import simplify
|
|
3
4
|
import copy
|
|
4
5
|
from fractions import Fraction
|
|
5
6
|
def abstractexpr(eq):
|
|
@@ -11,24 +12,26 @@ def abstractexpr(eq):
|
|
|
11
12
|
|
|
12
13
|
lst = factor_generation(eq)
|
|
13
14
|
deno = [item.children[0]**int(item.children[1].name[3:]) for item in lst if item.name == "f_pow" and item.children[1].name[:3] == "d_-"]
|
|
14
|
-
if eq.name == "f_mul" and any(item
|
|
15
|
-
return
|
|
15
|
+
if eq.name == "f_mul" and any(frac(item) is not None and frac(item) < 0 for item in lst):
|
|
16
|
+
return simplify(-eq, False).fx("neg")
|
|
16
17
|
if deno != []:
|
|
17
18
|
|
|
18
19
|
num = [item for item in lst if item.name != "f_pow" or item.children[1].name[:3] != "d_-"]
|
|
19
20
|
if num == []:
|
|
20
21
|
num = [tree_form("d_1")]
|
|
21
|
-
return TreeNode("f_div", [
|
|
22
|
+
return TreeNode("f_div", [simplify(product(num), False), simplify(product(deno), False)])
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
return TreeNode(eq.name, [abstractexpr(child) for child in eq.children])
|
|
25
26
|
|
|
26
27
|
def printeq_str(eq):
|
|
27
|
-
|
|
28
|
+
if eq is None:
|
|
29
|
+
return None
|
|
30
|
+
eq = merge_sqrt(eq)
|
|
31
|
+
return string_equation(str_form(dowhile(eq, abstractexpr)))
|
|
32
|
+
def printeq_obj(self):
|
|
33
|
+
return printeq_str(self)
|
|
28
34
|
|
|
29
35
|
def printeq(eq):
|
|
30
36
|
print(printeq_str(eq))
|
|
31
|
-
|
|
32
|
-
def printeq_log(lst):
|
|
33
|
-
for item in lst:
|
|
34
|
-
print(" "*item[0] + item[1])
|
|
37
|
+
TreeNode.__repr__ = printeq_obj
|