mathai 0.2.7__py3-none-any.whl → 0.2.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 +16 -16
- mathai/apart.py +103 -103
- mathai/base.py +355 -354
- mathai/console.py +84 -84
- mathai/diff.py +65 -65
- mathai/expand.py +58 -58
- mathai/factor.py +125 -125
- mathai/fraction.py +59 -59
- mathai/integrate.py +346 -346
- mathai/inverse.py +65 -65
- mathai/limit.py +130 -130
- mathai/linear.py +152 -152
- mathai/logic.py +224 -224
- mathai/parser.py +154 -154
- mathai/printeq.py +34 -34
- mathai/simplify.py +358 -358
- mathai/structure.py +103 -103
- mathai/tool.py +35 -35
- mathai/trig.py +169 -169
- mathai/univariate_inequality.py +410 -414
- {mathai-0.2.7.dist-info → mathai-0.2.9.dist-info}/METADATA +231 -231
- mathai-0.2.9.dist-info/RECORD +24 -0
- {mathai-0.2.7.dist-info → mathai-0.2.9.dist-info}/WHEEL +1 -1
- mathai-0.2.7.dist-info/RECORD +0 -24
- {mathai-0.2.7.dist-info → mathai-0.2.9.dist-info}/top_level.txt +0 -0
mathai/simplify.py
CHANGED
@@ -1,358 +1,358 @@
|
|
1
|
-
import math
|
2
|
-
from .base import *
|
3
|
-
from fractions import Fraction
|
4
|
-
|
5
|
-
def _solve(eq):
|
6
|
-
def solve_add(eq):
|
7
|
-
def multiplied(eq):
|
8
|
-
if eq.name[:2] == "d_":
|
9
|
-
return int(eq.name[2:]), "const"
|
10
|
-
if eq.name == "f_mul":
|
11
|
-
arth = 1
|
12
|
-
for i in range(len(eq.children)-1,-1,-1):
|
13
|
-
if eq.children[i].name[:2] == "d_":
|
14
|
-
arth *= int(eq.children[i].name[2:])
|
15
|
-
eq.children.pop(i)
|
16
|
-
if eq.children == []:
|
17
|
-
eq = "const"
|
18
|
-
elif len(eq.children) == 1:
|
19
|
-
eq = eq.children[0]
|
20
|
-
return arth, eq
|
21
|
-
return 1, eq
|
22
|
-
if eq.name != "f_add":
|
23
|
-
return eq
|
24
|
-
dic = {"const":0}
|
25
|
-
for child in eq.children:
|
26
|
-
a, b = multiplied(child)
|
27
|
-
if b == "const":
|
28
|
-
dic[b] += a
|
29
|
-
elif b in dic.keys():
|
30
|
-
dic[b] += a
|
31
|
-
else:
|
32
|
-
dic[b] = a
|
33
|
-
summation = TreeNode("f_add", [])
|
34
|
-
for key in sorted(dic.keys(), key=lambda x: str_form(x)):
|
35
|
-
n = dic[key]
|
36
|
-
if n == 0:
|
37
|
-
continue
|
38
|
-
if key == "const":
|
39
|
-
summation.children.append(tree_form("d_"+str(n)))
|
40
|
-
else:
|
41
|
-
if n == 1:
|
42
|
-
summation.children.append(key)
|
43
|
-
else:
|
44
|
-
if key.name == "f_mul":
|
45
|
-
key.children.append(tree_form("d_"+str(n)))
|
46
|
-
else:
|
47
|
-
key = tree_form("d_"+str(n))*key
|
48
|
-
summation.children.append(key)
|
49
|
-
|
50
|
-
if len(summation.children)==1:
|
51
|
-
summation = summation.children[0]
|
52
|
-
|
53
|
-
if summation.name[:2] == "f_" and len(summation.children)==0:
|
54
|
-
summation = tree_form("d_0")
|
55
|
-
return summation
|
56
|
-
|
57
|
-
def solve_mul(eq):
|
58
|
-
def multiplied(eq):
|
59
|
-
if eq.name[:2] == "d_":
|
60
|
-
return int(eq.name[2:]), "const"
|
61
|
-
if eq.name != "f_pow" or eq.children[1].name[:2] != "d_":
|
62
|
-
return 1, eq
|
63
|
-
else:
|
64
|
-
return int(eq.children[1].name[2:]), eq.children[0]
|
65
|
-
if eq.name == "f_pow":
|
66
|
-
if eq.children[1] == 1:
|
67
|
-
return eq.children[0]
|
68
|
-
return eq
|
69
|
-
if eq.name != "f_mul":
|
70
|
-
return eq
|
71
|
-
|
72
|
-
dic = {"const":1}
|
73
|
-
for child in eq.children:
|
74
|
-
|
75
|
-
a, b = multiplied(child)
|
76
|
-
if b == "const":
|
77
|
-
dic[b] *= a
|
78
|
-
elif b in dic.keys():
|
79
|
-
dic[b] += a
|
80
|
-
else:
|
81
|
-
dic[b] = a
|
82
|
-
|
83
|
-
summation = TreeNode("f_mul", [])
|
84
|
-
if dic["const"] == 0:
|
85
|
-
return tree_form("d_0")
|
86
|
-
for key in sorted(dic.keys(), key=lambda x: str_form(x)):
|
87
|
-
n = dic[key]
|
88
|
-
if n == 0:
|
89
|
-
|
90
|
-
continue
|
91
|
-
if key == "const":
|
92
|
-
if n != 1:
|
93
|
-
summation.children.append(tree_form("d_"+str(n)))
|
94
|
-
else:
|
95
|
-
if n== 1:
|
96
|
-
summation.children.append(key)
|
97
|
-
else:
|
98
|
-
summation.children.append(key**tree_form("d_"+str(n)))
|
99
|
-
|
100
|
-
if len(summation.children)==1:
|
101
|
-
summation = summation.children[0]
|
102
|
-
|
103
|
-
if summation.name[:2] == "f_" and len(summation.children)==0:
|
104
|
-
summation = tree_form("d_1")
|
105
|
-
|
106
|
-
return summation
|
107
|
-
def solve_u(eq):
|
108
|
-
if eq.name in ["f_pow", "f_mul"]:
|
109
|
-
return solve_mul(eq)
|
110
|
-
return solve_add(eq)
|
111
|
-
def recur_solve(eq):
|
112
|
-
eq = solve_u(eq)
|
113
|
-
if eq.children == []:
|
114
|
-
pass
|
115
|
-
|
116
|
-
elif eq.name in ("f_add", "f_mul"):
|
117
|
-
merged_children = []
|
118
|
-
for child in eq.children:
|
119
|
-
if child.name == eq.name:
|
120
|
-
merged_children.extend(child.children)
|
121
|
-
else:
|
122
|
-
merged_children.append(child)
|
123
|
-
|
124
|
-
eq = TreeNode(eq.name, merged_children)
|
125
|
-
return TreeNode(eq.name, [recur_solve(child) for child in eq.children])
|
126
|
-
|
127
|
-
return recur_solve(eq)
|
128
|
-
def _convert_sub2neg(eq):
|
129
|
-
if eq.name == "f_neg":
|
130
|
-
return -_convert_sub2neg(eq.children[0])
|
131
|
-
elif eq.name == "f_sub":
|
132
|
-
return _convert_sub2neg(eq.children[0]) - _convert_sub2neg(eq.children[1])
|
133
|
-
elif eq.name == "f_sqrt":
|
134
|
-
return _convert_sub2neg(eq.children[0])**(tree_form("d_2")**-1)
|
135
|
-
elif eq.name == "f_div":
|
136
|
-
if eq.children[0] == 0:
|
137
|
-
return tree_form("d_0")
|
138
|
-
return _convert_sub2neg(eq.children[0])*_convert_sub2neg(eq.children[1])**-1
|
139
|
-
return TreeNode(eq.name, [_convert_sub2neg(child) for child in eq.children])
|
140
|
-
def solve(eq, specialfx=False):
|
141
|
-
if specialfx:
|
142
|
-
eq = _convert_sub2neg(eq)
|
143
|
-
|
144
|
-
eq = flatten_tree(eq)
|
145
|
-
|
146
|
-
return dowhile(eq, _solve)
|
147
|
-
def solve2(eq):
|
148
|
-
return solve(eq, True)
|
149
|
-
def clear_div(eq, denom=False):
|
150
|
-
lst = factor_generation(eq)
|
151
|
-
if tree_form("d_0") in lst:
|
152
|
-
return tree_form("d_0")
|
153
|
-
lst3 = [item for item in lst if "v_" not in str_form(item) and compute(item) < 0]
|
154
|
-
|
155
|
-
sign = True
|
156
|
-
if len(lst3) % 2 == 1:
|
157
|
-
sign = False
|
158
|
-
if denom:
|
159
|
-
return eq if sign else -eq, sign
|
160
|
-
lst = [item for item in lst if not(item.name == "f_pow" and frac(item.children[1]) is not None and frac(item.children[1]) == -1)]
|
161
|
-
|
162
|
-
lst2 = [item for item in lst if "v_" in str_form(item)]
|
163
|
-
if lst2 == []:
|
164
|
-
return solve(product(lst)),sign
|
165
|
-
return solve(product(lst2)),sign
|
166
|
-
|
167
|
-
def simplify(eq):
|
168
|
-
error = False
|
169
|
-
eq = flatten_tree(eq)
|
170
|
-
if eq.name in ["f_and", "f_or", "f_not"]:
|
171
|
-
return TreeNode(eq.name, [simplify(child) for child in eq.children])
|
172
|
-
|
173
|
-
if eq.name in ["f_lt", "f_gt", "f_le", "f_ge", "f_eq"]:
|
174
|
-
tmp, sign = clear_div(simplify(eq.children[0]-eq.children[1]), eq.name != "f_eq")
|
175
|
-
name2 = eq.name
|
176
|
-
if not sign:
|
177
|
-
name2 = {"f_lt":"f_gt", "f_gt":"f_lt", "f_eq":"f_eq", "f_le":"f_ge", "f_ge":"f_le"}[name2]
|
178
|
-
|
179
|
-
return TreeNode(name2, [tmp, tree_form("d_0")])
|
180
|
-
|
181
|
-
eq = solve(eq, True)
|
182
|
-
def helper(eq):
|
183
|
-
|
184
|
-
if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and eq.children[1].name[:2] == "d_":
|
185
|
-
|
186
|
-
a, b = int(eq.children[0].name[2:]), int(eq.children[1].name[2:])
|
187
|
-
a = a**abs(b)
|
188
|
-
if b == 0 and a == 0:
|
189
|
-
error= True
|
190
|
-
return eq
|
191
|
-
if b == 0:
|
192
|
-
b = 1
|
193
|
-
b = int(b/abs(b))
|
194
|
-
if b == 1:
|
195
|
-
eq = tree_form("d_"+str(a))
|
196
|
-
else:
|
197
|
-
eq = tree_form("d_"+str(a))**-1
|
198
|
-
return TreeNode(eq.name, [helper(child) for child in eq.children])
|
199
|
-
def helper2(eq):
|
200
|
-
|
201
|
-
def even(eq):
|
202
|
-
return eq.name[:2] == "d_" and int(eq.name[2:])%2==0
|
203
|
-
def even2(eq):
|
204
|
-
return any(even(item) for item in factor_generation(eq))
|
205
|
-
if eq.name == "f_pow" and eq.children[0].name == "f_pow":
|
206
|
-
if even2(eq.children[0].children[1]) or even2(eq.children[1]) and not even2(solve(eq.children[0].children[1] * eq.children[1])):
|
207
|
-
return eq.children[0].children[0].fx("abs") ** solve(eq.children[0].children[1] * eq.children[1])
|
208
|
-
else:
|
209
|
-
return eq.children[0].children[0] ** solve(eq.children[0].children[1] * eq.children[1])
|
210
|
-
return TreeNode(eq.name, [helper2(child) for child in eq.children])
|
211
|
-
def helper3(eq):
|
212
|
-
|
213
|
-
if eq.name == "f_mul":
|
214
|
-
n = Fraction(1)
|
215
|
-
for i in range(len(eq.children)-1,-1,-1):
|
216
|
-
child= eq.children[i]
|
217
|
-
if child.name == "f_pow" and child.children[0].name[:2] == "d_" and child.children[1] == -1:
|
218
|
-
if int(child.children[0].name[2:]) == 0:
|
219
|
-
error = True
|
220
|
-
return eq
|
221
|
-
n = n*Fraction(1,int(child.children[0].name[2:]))
|
222
|
-
eq.children.pop(i)
|
223
|
-
elif child.name[:2] == "d_":
|
224
|
-
n = n*int(child.name[2:])
|
225
|
-
eq.children.pop(i)
|
226
|
-
if n.denominator == 1:
|
227
|
-
eq.children.append(tree_form("d_"+str(n.numerator)))
|
228
|
-
else:
|
229
|
-
eq.children.append(tree_form("d_"+str(n.numerator))*tree_form("d_"+str(n.denominator))**-1)
|
230
|
-
|
231
|
-
if len(eq.children) == 1:
|
232
|
-
eq = eq.children[0]
|
233
|
-
return TreeNode(eq.name, [helper3(child) for child in eq.children])
|
234
|
-
def helper4(eq):
|
235
|
-
nonlocal error
|
236
|
-
if eq == tree_form("d_-1")**tree_form("d_-1"):
|
237
|
-
return tree_form("d_-1")
|
238
|
-
def perfect_nth_root_value(x, n):
|
239
|
-
"""Return integer y if x is a perfect n-th power (y**n == x), else None."""
|
240
|
-
if x < 0 and n % 2 == 0:
|
241
|
-
return None # even root of negative number not real
|
242
|
-
|
243
|
-
sign = -1 if x < 0 else 1
|
244
|
-
x = abs(x)
|
245
|
-
|
246
|
-
# approximate integer root
|
247
|
-
y = round(x ** (1.0 / n))
|
248
|
-
|
249
|
-
if y ** n == x:
|
250
|
-
return sign * y
|
251
|
-
return None
|
252
|
-
def pp(eq, n):
|
253
|
-
if n == 1:
|
254
|
-
return eq
|
255
|
-
return eq**tree_form("d_"+str(n))
|
256
|
-
if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and frac(eq.children[1]) is not None:
|
257
|
-
f = frac(eq.children[1])
|
258
|
-
r = f.denominator
|
259
|
-
f = frac(eq.children[1]).numerator
|
260
|
-
if r > 1:
|
261
|
-
n = int(eq.children[0].name[2:])
|
262
|
-
if n < 0 and r==2:
|
263
|
-
out = perfect_nth_root_value(-n, 2)
|
264
|
-
if out is not None:
|
265
|
-
return pp( tree_form("d_"+str(out))*tree_form("s_i") , f)
|
266
|
-
else:
|
267
|
-
return pp( (tree_form("d_"+str(-n))**(tree_form("d_2")**-1))*tree_form("s_i"), f)
|
268
|
-
else:
|
269
|
-
out = perfect_nth_root_value(n, r)
|
270
|
-
if out is not None:
|
271
|
-
return pp( tree_form("d_"+str(out)), f)
|
272
|
-
if eq.name == "f_mul" and len(eq.children)== 2:
|
273
|
-
for i in range(2):
|
274
|
-
if eq.children[i].name[:2] == "d_" and eq.children[1-i].name == "f_log":
|
275
|
-
return (eq.children[1-i].children[0]**eq.children[i]).fx("log")
|
276
|
-
if eq.name == "f_pow" and eq.children[0] == tree_form("s_e") and eq.children[1].name == "f_log":
|
277
|
-
return eq.children[1].children[0]
|
278
|
-
if eq.name == "f_pow" and eq.children[0] == tree_form("d_1"):
|
279
|
-
eq = tree_form("d_1")
|
280
|
-
if eq.name == "f_pow" and eq.children[0] == tree_form("d_0"):
|
281
|
-
if frac(eq.children[1]) is not None and frac(eq.children[1]) <= 0:
|
282
|
-
error = True
|
283
|
-
else:
|
284
|
-
eq = tree_form("d_0")
|
285
|
-
if eq.name == "f_pow" and eq.children[0].name == "f_pow" and eq.children[0].children[1] == tree_form("d_2")**-1 and eq.children[1] == tree_form("d_2"):
|
286
|
-
eq = eq.children[0].children[0]
|
287
|
-
if (eq.name == "f_sin" and eq.children[0].name == "f_arcsin") or (eq.name == "f_cos" and eq.children[0].name == "f_arccos") or (eq.name == "f_tan" and eq.children[0].name == "f_arctan"):
|
288
|
-
eq = eq.children[0].children[0]
|
289
|
-
if (eq.name == "f_cos" and eq.children[0].name == "f_arcsin") or (eq.name == "f_sin" and eq.children[0].name == "f_arccos"):
|
290
|
-
eq2 = eq.children[0].children[0]
|
291
|
-
eq2 = (tree_form("d_1") - eq2*eq2)**(tree_form("d_1")/tree_form("d_2"))
|
292
|
-
eq = eq2
|
293
|
-
if (eq.name == "f_arcsin" and eq.children[0].name == "f_sin") or (eq.name == "f_arccos" and eq.children[0].name == "f_cos") or (eq.name == "f_arctan" and eq.children[0].name == "f_tan"):
|
294
|
-
eq = eq.children[0].children[0]
|
295
|
-
if eq.name == "f_abs" and eq.children[0].name[:2] == "d_":
|
296
|
-
eq = tree_form("d_"+str(abs(int(eq.children[0].name[2:]))))
|
297
|
-
|
298
|
-
if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and frac(eq.children[1]) is not None:
|
299
|
-
f = frac(eq.children[1])
|
300
|
-
if f.denominator != 1:
|
301
|
-
return helper(eq.children[0]**tree_form("d_"+str(f.numerator)))**(tree_form("d_"+str(f.denominator))**-1)
|
302
|
-
|
303
|
-
return TreeNode(eq.name, [helper4(child) for child in eq.children])
|
304
|
-
|
305
|
-
def helper7(eq):
|
306
|
-
|
307
|
-
if eq.name == "f_pow" and eq.children[0].name == "f_mul":
|
308
|
-
return product([child**eq.children[1] for child in eq.children[0].children])
|
309
|
-
return TreeNode(eq.name, [helper7(child) for child in eq.children])
|
310
|
-
|
311
|
-
def helper6(eq):
|
312
|
-
if eq.name == "f_mul":
|
313
|
-
lst = factor_generation(eq)
|
314
|
-
rm = []
|
315
|
-
for i in range(len(lst)):
|
316
|
-
if i in rm:
|
317
|
-
continue
|
318
|
-
for j in range(len(lst)):
|
319
|
-
if i ==j or j in rm:
|
320
|
-
continue
|
321
|
-
if solve(helper2(lst[i]**-1)) == lst[j]:
|
322
|
-
rm += [i,j]
|
323
|
-
break
|
324
|
-
if rm != []:
|
325
|
-
for item in sorted(rm)[::-1]:
|
326
|
-
lst.pop(item)
|
327
|
-
return product(lst)
|
328
|
-
return TreeNode(eq.name, [helper6(child) for child in eq.children])
|
329
|
-
def helper5(eq):
|
330
|
-
|
331
|
-
if eq.name == "f_pow" and eq.children[1].name[:2] == "d_" and abs(int(eq.children[1].name[2:]))%2==0 and eq.children[0].name == "f_abs":
|
332
|
-
return eq.children[0].children[0]**eq.children[1]
|
333
|
-
return TreeNode(eq.name, [helper5(child) for child in eq.children])
|
334
|
-
def helper8(eq):
|
335
|
-
if eq.name == "f_pow" and eq.children[0].name == "f_abs" and frac(eq.children[1]) is not None and frac(eq.children[1]).numerator % 2==0:
|
336
|
-
return eq.children[0].children[0] ** eq.children[1]
|
337
|
-
if eq.name == "f_abs" and eq.children[0].name == "f_abs":
|
338
|
-
return eq.children[0]
|
339
|
-
if eq.name == "f_cos" and eq.children[0].name == "f_abs":
|
340
|
-
return eq.children[0].children[0].fx("cos")
|
341
|
-
return TreeNode(eq.name, [helper8(child) for child in eq.children])
|
342
|
-
def fx1(eq):
|
343
|
-
for item in [helper, helper3, helper4, helper6,solve,helper2,helper5]:
|
344
|
-
eq = dowhile(eq, item)
|
345
|
-
return eq
|
346
|
-
def fx2(eq):
|
347
|
-
for item in [helper, helper3, helper4, helper6,helper7,helper2,helper5]:
|
348
|
-
eq = dowhile(eq, item)
|
349
|
-
return eq
|
350
|
-
def fx3(eq):
|
351
|
-
for item in [fx1, fx2]:
|
352
|
-
eq = dowhile(eq, item)
|
353
|
-
return eq
|
354
|
-
eq = dowhile(eq, fx3)
|
355
|
-
eq = dowhile(eq, helper8)
|
356
|
-
if error:
|
357
|
-
return None
|
358
|
-
return solve(eq)
|
1
|
+
import math
|
2
|
+
from .base import *
|
3
|
+
from fractions import Fraction
|
4
|
+
|
5
|
+
def _solve(eq):
|
6
|
+
def solve_add(eq):
|
7
|
+
def multiplied(eq):
|
8
|
+
if eq.name[:2] == "d_":
|
9
|
+
return int(eq.name[2:]), "const"
|
10
|
+
if eq.name == "f_mul":
|
11
|
+
arth = 1
|
12
|
+
for i in range(len(eq.children)-1,-1,-1):
|
13
|
+
if eq.children[i].name[:2] == "d_":
|
14
|
+
arth *= int(eq.children[i].name[2:])
|
15
|
+
eq.children.pop(i)
|
16
|
+
if eq.children == []:
|
17
|
+
eq = "const"
|
18
|
+
elif len(eq.children) == 1:
|
19
|
+
eq = eq.children[0]
|
20
|
+
return arth, eq
|
21
|
+
return 1, eq
|
22
|
+
if eq.name != "f_add":
|
23
|
+
return eq
|
24
|
+
dic = {"const":0}
|
25
|
+
for child in eq.children:
|
26
|
+
a, b = multiplied(child)
|
27
|
+
if b == "const":
|
28
|
+
dic[b] += a
|
29
|
+
elif b in dic.keys():
|
30
|
+
dic[b] += a
|
31
|
+
else:
|
32
|
+
dic[b] = a
|
33
|
+
summation = TreeNode("f_add", [])
|
34
|
+
for key in sorted(dic.keys(), key=lambda x: str_form(x)):
|
35
|
+
n = dic[key]
|
36
|
+
if n == 0:
|
37
|
+
continue
|
38
|
+
if key == "const":
|
39
|
+
summation.children.append(tree_form("d_"+str(n)))
|
40
|
+
else:
|
41
|
+
if n == 1:
|
42
|
+
summation.children.append(key)
|
43
|
+
else:
|
44
|
+
if key.name == "f_mul":
|
45
|
+
key.children.append(tree_form("d_"+str(n)))
|
46
|
+
else:
|
47
|
+
key = tree_form("d_"+str(n))*key
|
48
|
+
summation.children.append(key)
|
49
|
+
|
50
|
+
if len(summation.children)==1:
|
51
|
+
summation = summation.children[0]
|
52
|
+
|
53
|
+
if summation.name[:2] == "f_" and len(summation.children)==0:
|
54
|
+
summation = tree_form("d_0")
|
55
|
+
return summation
|
56
|
+
|
57
|
+
def solve_mul(eq):
|
58
|
+
def multiplied(eq):
|
59
|
+
if eq.name[:2] == "d_":
|
60
|
+
return int(eq.name[2:]), "const"
|
61
|
+
if eq.name != "f_pow" or eq.children[1].name[:2] != "d_":
|
62
|
+
return 1, eq
|
63
|
+
else:
|
64
|
+
return int(eq.children[1].name[2:]), eq.children[0]
|
65
|
+
if eq.name == "f_pow":
|
66
|
+
if eq.children[1] == 1:
|
67
|
+
return eq.children[0]
|
68
|
+
return eq
|
69
|
+
if eq.name != "f_mul":
|
70
|
+
return eq
|
71
|
+
|
72
|
+
dic = {"const":1}
|
73
|
+
for child in eq.children:
|
74
|
+
|
75
|
+
a, b = multiplied(child)
|
76
|
+
if b == "const":
|
77
|
+
dic[b] *= a
|
78
|
+
elif b in dic.keys():
|
79
|
+
dic[b] += a
|
80
|
+
else:
|
81
|
+
dic[b] = a
|
82
|
+
|
83
|
+
summation = TreeNode("f_mul", [])
|
84
|
+
if dic["const"] == 0:
|
85
|
+
return tree_form("d_0")
|
86
|
+
for key in sorted(dic.keys(), key=lambda x: str_form(x)):
|
87
|
+
n = dic[key]
|
88
|
+
if n == 0:
|
89
|
+
|
90
|
+
continue
|
91
|
+
if key == "const":
|
92
|
+
if n != 1:
|
93
|
+
summation.children.append(tree_form("d_"+str(n)))
|
94
|
+
else:
|
95
|
+
if n== 1:
|
96
|
+
summation.children.append(key)
|
97
|
+
else:
|
98
|
+
summation.children.append(key**tree_form("d_"+str(n)))
|
99
|
+
|
100
|
+
if len(summation.children)==1:
|
101
|
+
summation = summation.children[0]
|
102
|
+
|
103
|
+
if summation.name[:2] == "f_" and len(summation.children)==0:
|
104
|
+
summation = tree_form("d_1")
|
105
|
+
|
106
|
+
return summation
|
107
|
+
def solve_u(eq):
|
108
|
+
if eq.name in ["f_pow", "f_mul"]:
|
109
|
+
return solve_mul(eq)
|
110
|
+
return solve_add(eq)
|
111
|
+
def recur_solve(eq):
|
112
|
+
eq = solve_u(eq)
|
113
|
+
if eq.children == []:
|
114
|
+
pass
|
115
|
+
|
116
|
+
elif eq.name in ("f_add", "f_mul"):
|
117
|
+
merged_children = []
|
118
|
+
for child in eq.children:
|
119
|
+
if child.name == eq.name:
|
120
|
+
merged_children.extend(child.children)
|
121
|
+
else:
|
122
|
+
merged_children.append(child)
|
123
|
+
|
124
|
+
eq = TreeNode(eq.name, merged_children)
|
125
|
+
return TreeNode(eq.name, [recur_solve(child) for child in eq.children])
|
126
|
+
|
127
|
+
return recur_solve(eq)
|
128
|
+
def _convert_sub2neg(eq):
|
129
|
+
if eq.name == "f_neg":
|
130
|
+
return -_convert_sub2neg(eq.children[0])
|
131
|
+
elif eq.name == "f_sub":
|
132
|
+
return _convert_sub2neg(eq.children[0]) - _convert_sub2neg(eq.children[1])
|
133
|
+
elif eq.name == "f_sqrt":
|
134
|
+
return _convert_sub2neg(eq.children[0])**(tree_form("d_2")**-1)
|
135
|
+
elif eq.name == "f_div":
|
136
|
+
if eq.children[0] == 0:
|
137
|
+
return tree_form("d_0")
|
138
|
+
return _convert_sub2neg(eq.children[0])*_convert_sub2neg(eq.children[1])**-1
|
139
|
+
return TreeNode(eq.name, [_convert_sub2neg(child) for child in eq.children])
|
140
|
+
def solve(eq, specialfx=False):
|
141
|
+
if specialfx:
|
142
|
+
eq = _convert_sub2neg(eq)
|
143
|
+
|
144
|
+
eq = flatten_tree(eq)
|
145
|
+
|
146
|
+
return dowhile(eq, _solve)
|
147
|
+
def solve2(eq):
|
148
|
+
return solve(eq, True)
|
149
|
+
def clear_div(eq, denom=False):
|
150
|
+
lst = factor_generation(eq)
|
151
|
+
if tree_form("d_0") in lst:
|
152
|
+
return tree_form("d_0"), True
|
153
|
+
lst3 = [item for item in lst if "v_" not in str_form(item) and compute(item) < 0]
|
154
|
+
|
155
|
+
sign = True
|
156
|
+
if len(lst3) % 2 == 1:
|
157
|
+
sign = False
|
158
|
+
if denom:
|
159
|
+
return eq if sign else -eq, sign
|
160
|
+
lst = [item for item in lst if not(item.name == "f_pow" and frac(item.children[1]) is not None and frac(item.children[1]) == -1)]
|
161
|
+
|
162
|
+
lst2 = [item for item in lst if "v_" in str_form(item)]
|
163
|
+
if lst2 == []:
|
164
|
+
return solve(product(lst)),sign
|
165
|
+
return solve(product(lst2)),sign
|
166
|
+
|
167
|
+
def simplify(eq):
|
168
|
+
error = False
|
169
|
+
eq = flatten_tree(eq)
|
170
|
+
if eq.name in ["f_and", "f_or", "f_not"]:
|
171
|
+
return TreeNode(eq.name, [simplify(child) for child in eq.children])
|
172
|
+
|
173
|
+
if eq.name in ["f_lt", "f_gt", "f_le", "f_ge", "f_eq"]:
|
174
|
+
tmp, sign = clear_div(simplify(eq.children[0]-eq.children[1]), eq.name != "f_eq")
|
175
|
+
name2 = eq.name
|
176
|
+
if not sign:
|
177
|
+
name2 = {"f_lt":"f_gt", "f_gt":"f_lt", "f_eq":"f_eq", "f_le":"f_ge", "f_ge":"f_le"}[name2]
|
178
|
+
|
179
|
+
return TreeNode(name2, [tmp, tree_form("d_0")])
|
180
|
+
|
181
|
+
eq = solve(eq, True)
|
182
|
+
def helper(eq):
|
183
|
+
|
184
|
+
if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and eq.children[1].name[:2] == "d_":
|
185
|
+
|
186
|
+
a, b = int(eq.children[0].name[2:]), int(eq.children[1].name[2:])
|
187
|
+
a = a**abs(b)
|
188
|
+
if b == 0 and a == 0:
|
189
|
+
error= True
|
190
|
+
return eq
|
191
|
+
if b == 0:
|
192
|
+
b = 1
|
193
|
+
b = int(b/abs(b))
|
194
|
+
if b == 1:
|
195
|
+
eq = tree_form("d_"+str(a))
|
196
|
+
else:
|
197
|
+
eq = tree_form("d_"+str(a))**-1
|
198
|
+
return TreeNode(eq.name, [helper(child) for child in eq.children])
|
199
|
+
def helper2(eq):
|
200
|
+
|
201
|
+
def even(eq):
|
202
|
+
return eq.name[:2] == "d_" and int(eq.name[2:])%2==0
|
203
|
+
def even2(eq):
|
204
|
+
return any(even(item) for item in factor_generation(eq))
|
205
|
+
if eq.name == "f_pow" and eq.children[0].name == "f_pow":
|
206
|
+
if even2(eq.children[0].children[1]) or even2(eq.children[1]) and not even2(solve(eq.children[0].children[1] * eq.children[1])):
|
207
|
+
return eq.children[0].children[0].fx("abs") ** solve(eq.children[0].children[1] * eq.children[1])
|
208
|
+
else:
|
209
|
+
return eq.children[0].children[0] ** solve(eq.children[0].children[1] * eq.children[1])
|
210
|
+
return TreeNode(eq.name, [helper2(child) for child in eq.children])
|
211
|
+
def helper3(eq):
|
212
|
+
|
213
|
+
if eq.name == "f_mul":
|
214
|
+
n = Fraction(1)
|
215
|
+
for i in range(len(eq.children)-1,-1,-1):
|
216
|
+
child= eq.children[i]
|
217
|
+
if child.name == "f_pow" and child.children[0].name[:2] == "d_" and child.children[1] == -1:
|
218
|
+
if int(child.children[0].name[2:]) == 0:
|
219
|
+
error = True
|
220
|
+
return eq
|
221
|
+
n = n*Fraction(1,int(child.children[0].name[2:]))
|
222
|
+
eq.children.pop(i)
|
223
|
+
elif child.name[:2] == "d_":
|
224
|
+
n = n*int(child.name[2:])
|
225
|
+
eq.children.pop(i)
|
226
|
+
if n.denominator == 1:
|
227
|
+
eq.children.append(tree_form("d_"+str(n.numerator)))
|
228
|
+
else:
|
229
|
+
eq.children.append(tree_form("d_"+str(n.numerator))*tree_form("d_"+str(n.denominator))**-1)
|
230
|
+
|
231
|
+
if len(eq.children) == 1:
|
232
|
+
eq = eq.children[0]
|
233
|
+
return TreeNode(eq.name, [helper3(child) for child in eq.children])
|
234
|
+
def helper4(eq):
|
235
|
+
nonlocal error
|
236
|
+
if eq == tree_form("d_-1")**tree_form("d_-1"):
|
237
|
+
return tree_form("d_-1")
|
238
|
+
def perfect_nth_root_value(x, n):
|
239
|
+
"""Return integer y if x is a perfect n-th power (y**n == x), else None."""
|
240
|
+
if x < 0 and n % 2 == 0:
|
241
|
+
return None # even root of negative number not real
|
242
|
+
|
243
|
+
sign = -1 if x < 0 else 1
|
244
|
+
x = abs(x)
|
245
|
+
|
246
|
+
# approximate integer root
|
247
|
+
y = round(x ** (1.0 / n))
|
248
|
+
|
249
|
+
if y ** n == x:
|
250
|
+
return sign * y
|
251
|
+
return None
|
252
|
+
def pp(eq, n):
|
253
|
+
if n == 1:
|
254
|
+
return eq
|
255
|
+
return eq**tree_form("d_"+str(n))
|
256
|
+
if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and frac(eq.children[1]) is not None:
|
257
|
+
f = frac(eq.children[1])
|
258
|
+
r = f.denominator
|
259
|
+
f = frac(eq.children[1]).numerator
|
260
|
+
if r > 1:
|
261
|
+
n = int(eq.children[0].name[2:])
|
262
|
+
if n < 0 and r==2:
|
263
|
+
out = perfect_nth_root_value(-n, 2)
|
264
|
+
if out is not None:
|
265
|
+
return pp( tree_form("d_"+str(out))*tree_form("s_i") , f)
|
266
|
+
else:
|
267
|
+
return pp( (tree_form("d_"+str(-n))**(tree_form("d_2")**-1))*tree_form("s_i"), f)
|
268
|
+
else:
|
269
|
+
out = perfect_nth_root_value(n, r)
|
270
|
+
if out is not None:
|
271
|
+
return pp( tree_form("d_"+str(out)), f)
|
272
|
+
if eq.name == "f_mul" and len(eq.children)== 2:
|
273
|
+
for i in range(2):
|
274
|
+
if eq.children[i].name[:2] == "d_" and eq.children[1-i].name == "f_log":
|
275
|
+
return (eq.children[1-i].children[0]**eq.children[i]).fx("log")
|
276
|
+
if eq.name == "f_pow" and eq.children[0] == tree_form("s_e") and eq.children[1].name == "f_log":
|
277
|
+
return eq.children[1].children[0]
|
278
|
+
if eq.name == "f_pow" and eq.children[0] == tree_form("d_1"):
|
279
|
+
eq = tree_form("d_1")
|
280
|
+
if eq.name == "f_pow" and eq.children[0] == tree_form("d_0"):
|
281
|
+
if frac(eq.children[1]) is not None and frac(eq.children[1]) <= 0:
|
282
|
+
error = True
|
283
|
+
else:
|
284
|
+
eq = tree_form("d_0")
|
285
|
+
if eq.name == "f_pow" and eq.children[0].name == "f_pow" and eq.children[0].children[1] == tree_form("d_2")**-1 and eq.children[1] == tree_form("d_2"):
|
286
|
+
eq = eq.children[0].children[0]
|
287
|
+
if (eq.name == "f_sin" and eq.children[0].name == "f_arcsin") or (eq.name == "f_cos" and eq.children[0].name == "f_arccos") or (eq.name == "f_tan" and eq.children[0].name == "f_arctan"):
|
288
|
+
eq = eq.children[0].children[0]
|
289
|
+
if (eq.name == "f_cos" and eq.children[0].name == "f_arcsin") or (eq.name == "f_sin" and eq.children[0].name == "f_arccos"):
|
290
|
+
eq2 = eq.children[0].children[0]
|
291
|
+
eq2 = (tree_form("d_1") - eq2*eq2)**(tree_form("d_1")/tree_form("d_2"))
|
292
|
+
eq = eq2
|
293
|
+
if (eq.name == "f_arcsin" and eq.children[0].name == "f_sin") or (eq.name == "f_arccos" and eq.children[0].name == "f_cos") or (eq.name == "f_arctan" and eq.children[0].name == "f_tan"):
|
294
|
+
eq = eq.children[0].children[0]
|
295
|
+
if eq.name == "f_abs" and eq.children[0].name[:2] == "d_":
|
296
|
+
eq = tree_form("d_"+str(abs(int(eq.children[0].name[2:]))))
|
297
|
+
|
298
|
+
if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and frac(eq.children[1]) is not None:
|
299
|
+
f = frac(eq.children[1])
|
300
|
+
if f.denominator != 1:
|
301
|
+
return helper(eq.children[0]**tree_form("d_"+str(f.numerator)))**(tree_form("d_"+str(f.denominator))**-1)
|
302
|
+
|
303
|
+
return TreeNode(eq.name, [helper4(child) for child in eq.children])
|
304
|
+
|
305
|
+
def helper7(eq):
|
306
|
+
|
307
|
+
if eq.name == "f_pow" and eq.children[0].name == "f_mul":
|
308
|
+
return product([child**eq.children[1] for child in eq.children[0].children])
|
309
|
+
return TreeNode(eq.name, [helper7(child) for child in eq.children])
|
310
|
+
|
311
|
+
def helper6(eq):
|
312
|
+
if eq.name == "f_mul":
|
313
|
+
lst = factor_generation(eq)
|
314
|
+
rm = []
|
315
|
+
for i in range(len(lst)):
|
316
|
+
if i in rm:
|
317
|
+
continue
|
318
|
+
for j in range(len(lst)):
|
319
|
+
if i ==j or j in rm:
|
320
|
+
continue
|
321
|
+
if solve(helper2(lst[i]**-1)) == lst[j]:
|
322
|
+
rm += [i,j]
|
323
|
+
break
|
324
|
+
if rm != []:
|
325
|
+
for item in sorted(rm)[::-1]:
|
326
|
+
lst.pop(item)
|
327
|
+
return product(lst)
|
328
|
+
return TreeNode(eq.name, [helper6(child) for child in eq.children])
|
329
|
+
def helper5(eq):
|
330
|
+
|
331
|
+
if eq.name == "f_pow" and eq.children[1].name[:2] == "d_" and abs(int(eq.children[1].name[2:]))%2==0 and eq.children[0].name == "f_abs":
|
332
|
+
return eq.children[0].children[0]**eq.children[1]
|
333
|
+
return TreeNode(eq.name, [helper5(child) for child in eq.children])
|
334
|
+
def helper8(eq):
|
335
|
+
if eq.name == "f_pow" and eq.children[0].name == "f_abs" and frac(eq.children[1]) is not None and frac(eq.children[1]).numerator % 2==0:
|
336
|
+
return eq.children[0].children[0] ** eq.children[1]
|
337
|
+
if eq.name == "f_abs" and eq.children[0].name == "f_abs":
|
338
|
+
return eq.children[0]
|
339
|
+
if eq.name == "f_cos" and eq.children[0].name == "f_abs":
|
340
|
+
return eq.children[0].children[0].fx("cos")
|
341
|
+
return TreeNode(eq.name, [helper8(child) for child in eq.children])
|
342
|
+
def fx1(eq):
|
343
|
+
for item in [helper, helper3, helper4, helper6,solve,helper2,helper5]:
|
344
|
+
eq = dowhile(eq, item)
|
345
|
+
return eq
|
346
|
+
def fx2(eq):
|
347
|
+
for item in [helper, helper3, helper4, helper6,helper7,helper2,helper5]:
|
348
|
+
eq = dowhile(eq, item)
|
349
|
+
return eq
|
350
|
+
def fx3(eq):
|
351
|
+
for item in [fx1, fx2]:
|
352
|
+
eq = dowhile(eq, item)
|
353
|
+
return eq
|
354
|
+
eq = dowhile(eq, fx3)
|
355
|
+
eq = dowhile(eq, helper8)
|
356
|
+
if error:
|
357
|
+
return None
|
358
|
+
return solve(eq)
|