mathai 0.6.0__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 +53 -0
- mathai/apart.py +142 -0
- mathai/base.py +419 -0
- mathai/bivariate_inequality.py +317 -0
- mathai/console.py +84 -0
- mathai/diff.py +68 -0
- mathai/expand.py +124 -0
- mathai/factor.py +304 -0
- mathai/fraction.py +103 -0
- mathai/integrate.py +459 -0
- mathai/inverse.py +65 -0
- mathai/limit.py +156 -0
- mathai/linear.py +165 -0
- mathai/logic.py +230 -0
- mathai/matrix.py +22 -0
- mathai/ode.py +124 -0
- mathai/parser.py +158 -0
- mathai/printeq.py +34 -0
- mathai/simplify.py +521 -0
- mathai/structure.py +103 -0
- mathai/tool.py +163 -0
- mathai/trig.py +276 -0
- mathai/univariate_inequality.py +458 -0
- mathai-0.6.0.dist-info/METADATA +234 -0
- mathai-0.6.0.dist-info/RECORD +27 -0
- mathai-0.6.0.dist-info/WHEEL +5 -0
- mathai-0.6.0.dist-info/top_level.txt +1 -0
mathai/integrate.py
ADDED
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
from .factor import factor2
|
|
2
|
+
from .parser import parse
|
|
3
|
+
import itertools
|
|
4
|
+
from .diff import diff
|
|
5
|
+
from .fraction import fraction
|
|
6
|
+
from .simplify import simplify
|
|
7
|
+
from .expand import expand
|
|
8
|
+
from .base import *
|
|
9
|
+
from .printeq import printeq_str
|
|
10
|
+
from .structure import transform_formula
|
|
11
|
+
from .inverse import inverse
|
|
12
|
+
from .tool import poly
|
|
13
|
+
from fractions import Fraction
|
|
14
|
+
from .printeq import printeq
|
|
15
|
+
from .trig import trig0, trig2, trig3, trig4
|
|
16
|
+
from .apart import apart
|
|
17
|
+
|
|
18
|
+
def integrate_summation(equation):
|
|
19
|
+
if equation.name == "f_ref":
|
|
20
|
+
return equation
|
|
21
|
+
|
|
22
|
+
eq2 = equation
|
|
23
|
+
if eq2.name == "f_integrate":
|
|
24
|
+
equation = eq2.children[0]
|
|
25
|
+
wrt = eq2.children[1]
|
|
26
|
+
if equation.name == "f_add":
|
|
27
|
+
return summation([TreeNode("f_integrate", [child, wrt]) for child in equation.children])
|
|
28
|
+
equation = eq2
|
|
29
|
+
|
|
30
|
+
return TreeNode(equation.name, [integrate_summation(child) for child in equation.children])
|
|
31
|
+
def subs_heuristic(eq, var):
|
|
32
|
+
output = []
|
|
33
|
+
def collect2(eq):
|
|
34
|
+
if eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]) == Fraction(1,2):
|
|
35
|
+
|
|
36
|
+
if eq.children[0] == var:
|
|
37
|
+
output.append(str_form(eq))
|
|
38
|
+
if eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]).denominator == 1 and abs(frac(eq.children[1]).numerator) % 2 == 0:
|
|
39
|
+
if len(eq.children[0].children) == 0 or eq.children[0].children[0] == var:
|
|
40
|
+
output.append(str_form(eq.children[0]**2))
|
|
41
|
+
if eq.name in ["f_pow", "f_sin", "f_cos", "f_arcsin"] and var.name in str_form(eq.children[0]):
|
|
42
|
+
if eq.children[0].name[:2] != "v_":
|
|
43
|
+
output.append(str_form(eq.children[0]))
|
|
44
|
+
if eq.name in ["f_sin", "f_cos"]:
|
|
45
|
+
output.append(str_form(eq))
|
|
46
|
+
if eq.name == "f_pow" and eq.children[0].name == "s_e" and "v_" in str_form(eq):
|
|
47
|
+
if eq.children[1].name[:2] != "v_":
|
|
48
|
+
output.append(str_form(eq.children[1]))
|
|
49
|
+
output.append(str_form(eq))
|
|
50
|
+
for child in eq.children:
|
|
51
|
+
collect2(child)
|
|
52
|
+
def collect3(eq):
|
|
53
|
+
if eq.name in ["f_sin", "f_cos"]:
|
|
54
|
+
output.append(str_form(eq.children[0].fx("cos")))
|
|
55
|
+
for child in eq.children:
|
|
56
|
+
collect3(child)
|
|
57
|
+
collect2(eq)
|
|
58
|
+
|
|
59
|
+
if output == []:
|
|
60
|
+
collect3(eq)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
tmp = list(set([simplify(tree_form(x)) for x in output]))
|
|
64
|
+
tmp = sorted(tmp, key=lambda x: len(str(x)))
|
|
65
|
+
poly_term = None
|
|
66
|
+
term_degree = 100
|
|
67
|
+
output = []
|
|
68
|
+
for item in tmp:
|
|
69
|
+
n = poly(simplify(item), var.name)
|
|
70
|
+
if n is None:
|
|
71
|
+
output.append(item)
|
|
72
|
+
else:
|
|
73
|
+
if term_degree > len(n):
|
|
74
|
+
poly_term = item
|
|
75
|
+
term_degree = len(n)
|
|
76
|
+
if poly_term is None:
|
|
77
|
+
return tmp
|
|
78
|
+
return [poly_term]+output
|
|
79
|
+
try_index = []
|
|
80
|
+
try_lst = []
|
|
81
|
+
def ref(eq):
|
|
82
|
+
'''
|
|
83
|
+
if eq.name in ["f_try", "f_ref"]:
|
|
84
|
+
return eq
|
|
85
|
+
'''
|
|
86
|
+
if eq.name == "f_integrate":
|
|
87
|
+
return TreeNode("f_try", [eq.fx("ref"), eq])
|
|
88
|
+
return TreeNode(eq.name, [ref(child) for child in eq.children])
|
|
89
|
+
def place_try(eq):
|
|
90
|
+
global try_index
|
|
91
|
+
if eq.name == "f_try":
|
|
92
|
+
try_index.append(list(range(len(eq.children))))
|
|
93
|
+
return TreeNode(eq.name, [place_try(child) for child in eq.children])
|
|
94
|
+
def place_try2(eq):
|
|
95
|
+
global try_lst
|
|
96
|
+
if eq.name == "f_try":
|
|
97
|
+
return eq.children[try_lst.pop(0)]
|
|
98
|
+
return TreeNode(eq.name, [place_try2(child) for child in eq.children])
|
|
99
|
+
def _solve_integrate(eq):
|
|
100
|
+
if eq.name == "f_ref":
|
|
101
|
+
return eq
|
|
102
|
+
if eq.name == "f_subs":
|
|
103
|
+
if all(item not in str_form(eq.children[0]) for item in ["f_integrate", "f_subs", "f_try"]):
|
|
104
|
+
return replace(eq.children[0], eq.children[1], eq.children[2])
|
|
105
|
+
|
|
106
|
+
if eq.name == "f_try":
|
|
107
|
+
for child in eq.children:
|
|
108
|
+
if all(item not in str_form(child) for item in ["f_integrate", "f_subs", "f_try"]):
|
|
109
|
+
return child
|
|
110
|
+
return TreeNode(eq.name, [_solve_integrate(child) for child in eq.children])
|
|
111
|
+
def handle_try(eq):
|
|
112
|
+
global try_lst, try_index
|
|
113
|
+
if eq.name == "f_try":
|
|
114
|
+
try_lst = []
|
|
115
|
+
try_index = []
|
|
116
|
+
for child in eq.children:
|
|
117
|
+
place_try(child)
|
|
118
|
+
output = []
|
|
119
|
+
for item in itertools.product(*try_index):
|
|
120
|
+
try_lst = list(item)
|
|
121
|
+
output += [place_try2(child) for child in eq.children]
|
|
122
|
+
|
|
123
|
+
return TreeNode("f_try", output)
|
|
124
|
+
else:
|
|
125
|
+
return TreeNode(eq.name, [handle_try(child) for child in eq.children])
|
|
126
|
+
def inteq(eq):
|
|
127
|
+
if eq.name == "f_try":
|
|
128
|
+
eq2 = None
|
|
129
|
+
output = []
|
|
130
|
+
for child in eq.children:
|
|
131
|
+
if child.name == "f_ref":
|
|
132
|
+
eq2 = child.children[0]
|
|
133
|
+
break
|
|
134
|
+
if eq2 is None:
|
|
135
|
+
return eq
|
|
136
|
+
printeq(eq)
|
|
137
|
+
for child in eq.children:
|
|
138
|
+
if child.name == "f_ref":
|
|
139
|
+
output.append(child)
|
|
140
|
+
else:
|
|
141
|
+
eq3 = simplify(expand(simplify(eq2 - child)))
|
|
142
|
+
if contain(eq3, eq2):
|
|
143
|
+
out = inverse(eq3, str_form(eq2))
|
|
144
|
+
if out is None:
|
|
145
|
+
output.append(child)
|
|
146
|
+
else:
|
|
147
|
+
output.append(out)
|
|
148
|
+
else:
|
|
149
|
+
output.append(child)
|
|
150
|
+
printeq(TreeNode("f_try", output))
|
|
151
|
+
print()
|
|
152
|
+
return TreeNode("f_try", output)
|
|
153
|
+
else:
|
|
154
|
+
return TreeNode(eq.name, [inteq(child) for child in eq.children])
|
|
155
|
+
def rm(eq):
|
|
156
|
+
if eq.name == "f_try":
|
|
157
|
+
eq = TreeNode(eq.name, list(set(eq.children)))
|
|
158
|
+
return TreeNode(eq.name, [rm(child) for child in eq.children if child is not None])
|
|
159
|
+
def solve_integrate(eq):
|
|
160
|
+
|
|
161
|
+
eq2 = dowhile(eq, _solve_integrate)
|
|
162
|
+
eq2 = dowhile(eq2, handle_try)
|
|
163
|
+
eq2 = rm(eq2)
|
|
164
|
+
if eq2.name == "f_try":
|
|
165
|
+
eq2.children = list(set(eq2.children))
|
|
166
|
+
return eq2
|
|
167
|
+
def integrate_subs(equation, term, v1, v2):
|
|
168
|
+
output = []
|
|
169
|
+
orig = equation.copy_tree()
|
|
170
|
+
none = TreeNode("f_integrate",[orig, tree_form(v1)])
|
|
171
|
+
origv2 = copy.deepcopy(v2)
|
|
172
|
+
equation = simplify(equation)
|
|
173
|
+
eq = equation
|
|
174
|
+
termeq = term
|
|
175
|
+
t = inverse(copy.deepcopy(termeq), v1)
|
|
176
|
+
|
|
177
|
+
g = inverse(termeq, v2)
|
|
178
|
+
|
|
179
|
+
if g is None:
|
|
180
|
+
return none
|
|
181
|
+
if t is None:
|
|
182
|
+
return none
|
|
183
|
+
else:
|
|
184
|
+
|
|
185
|
+
t = expand(t)
|
|
186
|
+
eq = replace(eq, tree_form(v1), t)
|
|
187
|
+
|
|
188
|
+
eq2 = replace(diff(g, v1), tree_form(v1), t)
|
|
189
|
+
equation = eq/eq2
|
|
190
|
+
equation = simplify(equation)
|
|
191
|
+
|
|
192
|
+
if v1 in str_form(equation):
|
|
193
|
+
|
|
194
|
+
return none
|
|
195
|
+
|
|
196
|
+
return dowhile(TreeNode("f_subs", [TreeNode("f_integrate", [simplify(equation), tree_form(origv2)]),tree_form(origv2) ,g]), trig0)
|
|
197
|
+
|
|
198
|
+
def integrate_subs_main(equation):
|
|
199
|
+
if equation.name == "f_ref":
|
|
200
|
+
return equation
|
|
201
|
+
eq2 = equation
|
|
202
|
+
if eq2.name == "f_integrate":
|
|
203
|
+
output = [eq2]
|
|
204
|
+
wrt = eq2.children[1]
|
|
205
|
+
eq = equation.children[0]
|
|
206
|
+
v2 = "v_"+str(int(wrt.name[2:])+1)
|
|
207
|
+
for item in subs_heuristic(eq, wrt):
|
|
208
|
+
x = tree_form(v2)-item
|
|
209
|
+
output.append(integrate_subs(eq, x, wrt.name, v2))
|
|
210
|
+
output = list(set(output))
|
|
211
|
+
if len(output) == 1:
|
|
212
|
+
return output[0]
|
|
213
|
+
|
|
214
|
+
return TreeNode("f_try", [item.copy_tree() for item in output])
|
|
215
|
+
else:
|
|
216
|
+
return TreeNode(equation.name, [integrate_subs_main(child) for child in equation.children])
|
|
217
|
+
|
|
218
|
+
def _sqint(equation):
|
|
219
|
+
def sgn(eq):
|
|
220
|
+
if compute(eq) <0:
|
|
221
|
+
return tree_form("d_-1"), tree_form("d_-1")*eq
|
|
222
|
+
return tree_form("d_1"), eq
|
|
223
|
+
eq2 = equation
|
|
224
|
+
if eq2.name == "f_integrate":
|
|
225
|
+
equation = eq2.children[0]
|
|
226
|
+
var = eq2.children[1]
|
|
227
|
+
|
|
228
|
+
one = tree_form("d_1")
|
|
229
|
+
two = tree_form("d_2")
|
|
230
|
+
four = tree_form("d_4")
|
|
231
|
+
three = tree_form("d_3")
|
|
232
|
+
root = tree_form("d_2")**-1
|
|
233
|
+
zero = tree_form("d_0")
|
|
234
|
+
|
|
235
|
+
n, d = num_dem(equation)
|
|
236
|
+
n, d = simplify(n), simplify(d)
|
|
237
|
+
term = [simplify(x) for x in factor_generation(d)]
|
|
238
|
+
const = product([item for item in term if "v_" not in str_form(item)])
|
|
239
|
+
term = [item for item in term if "v_" in str_form(item)]
|
|
240
|
+
mode = False
|
|
241
|
+
if all(item.name == "f_pow" and simplify(item.children[1]-root) == zero for item in term):
|
|
242
|
+
d = simplify(expand(const**two*product([item.children[0] for item in term])))
|
|
243
|
+
else:
|
|
244
|
+
mode = True
|
|
245
|
+
if any(item.name == "f_pow" and simplify(item.children[1]-root) == zero for item in term):
|
|
246
|
+
return None
|
|
247
|
+
if vlist(equation) == []:
|
|
248
|
+
return None
|
|
249
|
+
v = vlist(equation)[0]
|
|
250
|
+
x = tree_form(v)
|
|
251
|
+
|
|
252
|
+
np = poly(n, v)
|
|
253
|
+
|
|
254
|
+
dp = poly(d, v)
|
|
255
|
+
|
|
256
|
+
if np is None or dp is None:
|
|
257
|
+
return None
|
|
258
|
+
|
|
259
|
+
if len(np) == 1 and len(dp) == 3:
|
|
260
|
+
k, a, b, c = np+dp
|
|
261
|
+
if a == zero:
|
|
262
|
+
return None
|
|
263
|
+
s1, s2 = sgn(a)
|
|
264
|
+
const = (four*a*c - b**two)/(four*a)
|
|
265
|
+
t1, t2 = sgn(const)
|
|
266
|
+
la = s2**root
|
|
267
|
+
lb = b*s2**root/(two*a)
|
|
268
|
+
|
|
269
|
+
if mode:
|
|
270
|
+
if s1 == one:
|
|
271
|
+
if t1 == one:
|
|
272
|
+
return k*((la*x+lb)/t2**root).fx("arctan")/(la * t2**root)
|
|
273
|
+
else:
|
|
274
|
+
return None
|
|
275
|
+
else:
|
|
276
|
+
if t1 == one:
|
|
277
|
+
return None
|
|
278
|
+
else:
|
|
279
|
+
_, t2 = sgn(-const)
|
|
280
|
+
return -k*((la*x+lb)/t2**root).fx("arctan")/(la * t2**root)
|
|
281
|
+
if s1 == one:
|
|
282
|
+
if t1 == one:
|
|
283
|
+
return simplify(k*(la*x + lb + ((la*x + lb)**two + t2)**root).fx("abs").fx("log")/la)
|
|
284
|
+
else:
|
|
285
|
+
return simplify(k*(la*x + lb + ((la*x + lb)**two - t2)**root).fx("abs").fx("log")/la)
|
|
286
|
+
|
|
287
|
+
else:
|
|
288
|
+
if t1 == one:
|
|
289
|
+
return k*((la*x + lb)/t2**root).fx("arcsin")/la
|
|
290
|
+
else:
|
|
291
|
+
return None
|
|
292
|
+
if len(np) == 2 and len(dp) == 3:
|
|
293
|
+
|
|
294
|
+
p, q, a, b, c = np+dp
|
|
295
|
+
if a == zero:
|
|
296
|
+
return None
|
|
297
|
+
A = p/(two*a)
|
|
298
|
+
B = q - A*b
|
|
299
|
+
t = a*x**two + b*x + c
|
|
300
|
+
|
|
301
|
+
if not mode:
|
|
302
|
+
tmp = _sqint(TreeNode("f_integrate", [simplify(one/t**root), var]))
|
|
303
|
+
if tmp is None:
|
|
304
|
+
tmp = TreeNode("f_integrate", [simplify(one/t**root), var])
|
|
305
|
+
return A*two*t**root + tmp*B
|
|
306
|
+
else:
|
|
307
|
+
tmp = _sqint(TreeNode("f_integrate", [simplify(one/t), var]))
|
|
308
|
+
if tmp is None:
|
|
309
|
+
tmp = TreeNode("f_integrate", [simplify(one/t), var])
|
|
310
|
+
return A*t.fx("abs").fx("log") + tmp*B
|
|
311
|
+
equation = eq2
|
|
312
|
+
coll = TreeNode(equation.name, [])
|
|
313
|
+
for child in equation.children:
|
|
314
|
+
out = _sqint(child)
|
|
315
|
+
if out is None:
|
|
316
|
+
coll.children.append(child)
|
|
317
|
+
else:
|
|
318
|
+
coll.children.append(out)
|
|
319
|
+
return coll
|
|
320
|
+
|
|
321
|
+
def sqint(eq):
|
|
322
|
+
out = simplify(_sqint(eq))
|
|
323
|
+
if out is None:
|
|
324
|
+
return eq
|
|
325
|
+
return out
|
|
326
|
+
|
|
327
|
+
def byparts(eq):
|
|
328
|
+
if eq.name == "f_ref":
|
|
329
|
+
return eq
|
|
330
|
+
eq2 = eq
|
|
331
|
+
if eq2.name == "f_integrate":
|
|
332
|
+
output = []
|
|
333
|
+
eq = eq2.children[0]
|
|
334
|
+
wrt = eq2.children[1]
|
|
335
|
+
lst = factor_generation(eq)
|
|
336
|
+
if len(lst) == 3 and len(list(set(lst))) == 1:
|
|
337
|
+
lst = [(lst[0]**2).copy_tree(), lst[0].copy_tree()]
|
|
338
|
+
if len(lst) == 3 and len(list(set(lst))) == 2:
|
|
339
|
+
lst2 = list(set(lst))
|
|
340
|
+
a, b = lst2
|
|
341
|
+
a = a**lst.count(a)
|
|
342
|
+
b = b**lst.count(b)
|
|
343
|
+
lst = [a.copy_tree(), b.copy_tree()]
|
|
344
|
+
if len(lst) == 1:
|
|
345
|
+
lst += [tree_form("d_1")]
|
|
346
|
+
if len(lst) == 2:
|
|
347
|
+
for i in range(2):
|
|
348
|
+
|
|
349
|
+
f, g = [lst[i], lst[1-i]]
|
|
350
|
+
if contain(f, tree_form("s_e")):
|
|
351
|
+
continue
|
|
352
|
+
out1 = TreeNode("f_integrate", [g.copy_tree(), wrt])
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
out2 = TreeNode("f_integrate", [simplify(diff(f.copy_tree(), wrt.name)*out1), wrt])
|
|
356
|
+
|
|
357
|
+
output.append(simplify(f.copy_tree() * out1 - out2))
|
|
358
|
+
if len(output) == 0:
|
|
359
|
+
pass
|
|
360
|
+
elif len(output) == 1:
|
|
361
|
+
return output[0]
|
|
362
|
+
else:
|
|
363
|
+
return TreeNode("f_try", output)
|
|
364
|
+
eq = eq2
|
|
365
|
+
return TreeNode(eq.name, [byparts(child) for child in eq.children])
|
|
366
|
+
|
|
367
|
+
def integration_formula_init():
|
|
368
|
+
var = "x"
|
|
369
|
+
formula_list = [
|
|
370
|
+
(f"(A*{var}+B)^C", f"(A*{var}+B)^(C+1)/(A*(C+1))"),
|
|
371
|
+
(f"sin(A*{var}+B)", f"-cos(A*{var}+B)/A"),
|
|
372
|
+
(f"cos(A*{var}+B)", f"sin(A*{var}+B)/A"),
|
|
373
|
+
(f"1/(A*{var}+B)", f"log(abs(A*{var}+B))/A"),
|
|
374
|
+
(f"e^(A*{var}+B)", f"e^(A*{var}+B)/A"),
|
|
375
|
+
(f"1/cos(A*{var}+B)", f"log(abs((1+sin(A*{var}+B))/cos(A*{var}+B)))"),
|
|
376
|
+
(f"1/cos(A*{var}+B)^2", f"tan(A*{var}+B)/A"),
|
|
377
|
+
(f"1/sin(A*{var}+B)", f"log(abs(tan((A*{var}+B)/2)))/A"),
|
|
378
|
+
(f"1/cos(A*{var}+B)^3", f"(sec(A*{var}+B)*tan(A*{var}+B)+log(abs(sec(A*{var}+B)+tan(A*{var}+B))))/(2*A)")
|
|
379
|
+
]
|
|
380
|
+
formula_list = [[simplify(parse(y)) for y in x] for x in formula_list]
|
|
381
|
+
expr = [[parse("A"), parse("1")], [parse("B"), parse("0")]]
|
|
382
|
+
return [formula_list, var, expr]
|
|
383
|
+
formula_gen = integration_formula_init()
|
|
384
|
+
def integration_formula_trig():
|
|
385
|
+
var = "x"
|
|
386
|
+
formula_list = [(f"(A+B*sin({var})+C*cos({var}))/(D+E*sin({var})+F*cos({var}))", f"((B*E+C*F)/(E^2+F^2))*{var}+((C*E-B*F)/(E^2+F^2))*log(D+E*sin({var})+F*cos({var}))")]
|
|
387
|
+
formula_list = [[simplify(parse(y)) for y in x] for x in formula_list]
|
|
388
|
+
expr = [[parse("A"), parse("0"), parse("1")], [parse("B"), parse("0"), parse("1")],\
|
|
389
|
+
[parse("C"), parse("0"), parse("1")], [parse("D"), parse("0"), parse("1")],\
|
|
390
|
+
[parse("E"), parse("0"), parse("1")], [parse("F"), parse("0"), parse("1")]]
|
|
391
|
+
return [formula_list, var, expr]
|
|
392
|
+
formula_gen4 = integration_formula_trig()
|
|
393
|
+
|
|
394
|
+
def integration_formula_ex():
|
|
395
|
+
var = "x"
|
|
396
|
+
formula_list = [
|
|
397
|
+
(
|
|
398
|
+
f"e^(A*{var})*cos(B*{var})",
|
|
399
|
+
f"e^(A*{var})*(A*cos(B*{var}) + B*sin(B*{var}))/(A^2 + B^2)"
|
|
400
|
+
)
|
|
401
|
+
]
|
|
402
|
+
formula_list = [[simplify(parse(y)) for y in x] for x in formula_list]
|
|
403
|
+
expr = [[parse("A"), parse("1")], [parse("B"), parse("1")]]
|
|
404
|
+
return [formula_list, var, expr]
|
|
405
|
+
|
|
406
|
+
formula_gen11 = integration_formula_ex()
|
|
407
|
+
def rm_const(equation):
|
|
408
|
+
if equation.name == "f_ref":
|
|
409
|
+
return equation
|
|
410
|
+
eq2 = equation
|
|
411
|
+
if eq2.name == "f_integrate" and contain(eq2.children[0], eq2.children[1]):
|
|
412
|
+
equation = eq2.children[0]
|
|
413
|
+
wrt = eq2.children[1]
|
|
414
|
+
|
|
415
|
+
lst = factor_generation(equation)
|
|
416
|
+
|
|
417
|
+
lst_const = [item for item in lst if not contain(item, wrt)]
|
|
418
|
+
if lst_const != []:
|
|
419
|
+
|
|
420
|
+
equation = product([item for item in lst if contain(item, wrt)]).copy_tree()
|
|
421
|
+
const = product(lst_const)
|
|
422
|
+
const = simplify(const)
|
|
423
|
+
|
|
424
|
+
if not contain(const, tree_form("s_i")):
|
|
425
|
+
|
|
426
|
+
return rm_const(TreeNode("f_integrate",[equation, wrt])) *const
|
|
427
|
+
equation = eq2
|
|
428
|
+
return TreeNode(equation.name, [rm_const(child) for child in equation.children])
|
|
429
|
+
|
|
430
|
+
def shorten(eq):
|
|
431
|
+
if eq.name.startswith("d_"):
|
|
432
|
+
return tree_form("d_0")
|
|
433
|
+
return TreeNode(eq.name, [shorten(child) for child in eq.children])
|
|
434
|
+
def integrate_formula(equation):
|
|
435
|
+
if equation.name == "f_ref":
|
|
436
|
+
return equation.copy_tree()
|
|
437
|
+
eq2 = equation.copy_tree()
|
|
438
|
+
if eq2.name == "f_integrate":
|
|
439
|
+
integrand = eq2.children[0]
|
|
440
|
+
wrt = eq2.children[1]
|
|
441
|
+
if integrand == wrt:
|
|
442
|
+
return wrt**2/2 # x^2/2
|
|
443
|
+
if not contain(integrand, wrt):
|
|
444
|
+
return integrand*wrt
|
|
445
|
+
out = transform_formula(simplify(trig0(integrand)), wrt.name, formula_gen[0], formula_gen[1], formula_gen[2])
|
|
446
|
+
if out is not None:
|
|
447
|
+
|
|
448
|
+
return out
|
|
449
|
+
expr_str = str_form(shorten(integrand))
|
|
450
|
+
if len(expr_str) < 30:
|
|
451
|
+
if expr_str.count("f_sin") + expr_str.count("f_cos") > 2:
|
|
452
|
+
out = transform_formula(integrand, wrt.name, formula_gen4[0], formula_gen4[1], formula_gen4[2])
|
|
453
|
+
if out is not None:
|
|
454
|
+
return out
|
|
455
|
+
if "f_cos" in expr_str and contain(integrand, tree_form("s_e")):
|
|
456
|
+
out = transform_formula(integrand, wrt.name, formula_gen11[0], formula_gen11[1], formula_gen11[2])
|
|
457
|
+
if out is not None:
|
|
458
|
+
return out
|
|
459
|
+
return TreeNode(eq2.name, [integrate_formula(child) for child in eq2.children])
|
mathai/inverse.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from .base import *
|
|
2
|
+
from .simplify import simplify
|
|
3
|
+
from .expand import expand
|
|
4
|
+
def inverse(rhs,term, sign=None):
|
|
5
|
+
term = tree_form(term)
|
|
6
|
+
lhs = tree_form("d_0")
|
|
7
|
+
count = 15
|
|
8
|
+
|
|
9
|
+
while not rhs==term:
|
|
10
|
+
if rhs.name == "f_add":
|
|
11
|
+
if all(term in factor_generation(child) for child in rhs.children):
|
|
12
|
+
newrhs = simplify(expand(rhs*term**-1))
|
|
13
|
+
if not contain(newrhs, term):
|
|
14
|
+
rhs = term * newrhs
|
|
15
|
+
else:
|
|
16
|
+
for i in range(len(rhs.children)-1,-1,-1):
|
|
17
|
+
if not contain(rhs.children[i], term):
|
|
18
|
+
lhs = lhs - rhs.children[i]
|
|
19
|
+
rhs.children.pop(i)
|
|
20
|
+
elif rhs.name == "f_mul":
|
|
21
|
+
for i in range(len(rhs.children)-1,-1,-1):
|
|
22
|
+
if not contain(rhs.children[i], term):
|
|
23
|
+
lhs = lhs * rhs.children[i]**-1
|
|
24
|
+
if sign is not None:
|
|
25
|
+
if "v_" in str_form(rhs.children[i]):
|
|
26
|
+
return None
|
|
27
|
+
if compute(rhs.children[i]**-1) < 0:
|
|
28
|
+
sign = not sign
|
|
29
|
+
|
|
30
|
+
rhs.children.pop(i)
|
|
31
|
+
elif rhs.name == "f_pow" and contain(rhs.children[0], term):
|
|
32
|
+
lhs = lhs ** (tree_form("d_1")/rhs.children[1])
|
|
33
|
+
rhs = copy.deepcopy(rhs.children[0])
|
|
34
|
+
elif rhs.name == "f_sin" and contain(rhs.children[0], term):
|
|
35
|
+
lhs = lhs.fx("arcsin")
|
|
36
|
+
rhs = copy.deepcopy(rhs.children[0])
|
|
37
|
+
elif rhs.name == "f_arcsin" and contain(rhs.children[0], term):
|
|
38
|
+
lhs = lhs.fx("sin")
|
|
39
|
+
rhs = copy.deepcopy(rhs.children[0])
|
|
40
|
+
elif rhs.name == "f_arccos" and contain(rhs.children[0], term):
|
|
41
|
+
lhs = lhs.fx("cos")
|
|
42
|
+
rhs = copy.deepcopy(rhs.children[0])
|
|
43
|
+
elif rhs.name == "f_cos" and contain(rhs.children[0], term):
|
|
44
|
+
lhs = lhs.fx("arccos")
|
|
45
|
+
rhs = copy.deepcopy(rhs.children[0])
|
|
46
|
+
elif rhs.name == "f_log" and contain(rhs.children[0], term):
|
|
47
|
+
lhs = tree_form("s_e")**lhs
|
|
48
|
+
rhs = copy.deepcopy(rhs.children[0])
|
|
49
|
+
elif rhs.name == "f_pow" and rhs.children[0].name == "s_e" and contain(rhs.children[1], term):
|
|
50
|
+
lhs = lhs.fx("log")
|
|
51
|
+
rhs = copy.deepcopy(rhs.children[1].fx("log"))
|
|
52
|
+
elif rhs.name == "f_tan" and contain(rhs.children[0], term):
|
|
53
|
+
lhs = lhs.fx("arctan")
|
|
54
|
+
rhs = copy.deepcopy(rhs.children[0])
|
|
55
|
+
elif rhs.name == "f_arctan" and contain(rhs.children[0], term):
|
|
56
|
+
lhs = lhs.fx("tan")
|
|
57
|
+
rhs = copy.deepcopy(rhs.children[0])
|
|
58
|
+
if len(rhs.children) == 1:
|
|
59
|
+
rhs = rhs.children[0]
|
|
60
|
+
count -= 1
|
|
61
|
+
if count == 0:
|
|
62
|
+
return None
|
|
63
|
+
if sign is None:
|
|
64
|
+
return simplify(lhs)
|
|
65
|
+
return simplify(lhs), sign
|
mathai/limit.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
from .structure import structure
|
|
2
|
+
from .base import *
|
|
3
|
+
from .parser import parse
|
|
4
|
+
from .simplify import simplify
|
|
5
|
+
from .expand import expand
|
|
6
|
+
from .diff import diff
|
|
7
|
+
from .trig import trig0
|
|
8
|
+
from .fraction import fraction
|
|
9
|
+
from .printeq import printeq
|
|
10
|
+
tab=0
|
|
11
|
+
def substitute_val(eq, val, var="v_0"):
|
|
12
|
+
eq = replace(eq, tree_form(var), tree_form("d_"+str(val)))
|
|
13
|
+
return eq
|
|
14
|
+
|
|
15
|
+
def subslimit(equation, var):
|
|
16
|
+
equation2 = trig0(replace(equation, var, tree_form("d_0")))
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
tmp = simplify(equation2)
|
|
20
|
+
return simplify(expand(tmp))
|
|
21
|
+
except:
|
|
22
|
+
return None
|
|
23
|
+
|
|
24
|
+
def check(num, den, var):
|
|
25
|
+
n, d = None, None
|
|
26
|
+
|
|
27
|
+
n, d = (dowhile(replace(e, tree_form(var), tree_form("d_0")), lambda x: trig0(simplify(x))) for e in (num, den))
|
|
28
|
+
|
|
29
|
+
if n is None or d is None:
|
|
30
|
+
return False
|
|
31
|
+
if n == 0 and d == 0: return True
|
|
32
|
+
if d != 0:
|
|
33
|
+
return simplify(n/d)
|
|
34
|
+
return False
|
|
35
|
+
def lhospital(num, den, steps,var):
|
|
36
|
+
|
|
37
|
+
out = check(num, den, var)
|
|
38
|
+
|
|
39
|
+
if isinstance(out, TreeNode):
|
|
40
|
+
return out
|
|
41
|
+
for _ in range(steps):
|
|
42
|
+
num2, den2 = map(lambda e: simplify(diff(e, var)), (num, den))
|
|
43
|
+
out = check(num2, den2, var)
|
|
44
|
+
if out is True:
|
|
45
|
+
num, den = num2, den2
|
|
46
|
+
continue
|
|
47
|
+
if out is False:
|
|
48
|
+
eq2 = simplify(fraction(simplify(num/den)))
|
|
49
|
+
return eq2
|
|
50
|
+
return out
|
|
51
|
+
def lhospital2(eq, var):
|
|
52
|
+
eq= simplify(eq)
|
|
53
|
+
if eq is None:
|
|
54
|
+
return None
|
|
55
|
+
if not contain(eq, tree_form(var)):
|
|
56
|
+
return eq
|
|
57
|
+
num, dem = [simplify(item) for item in num_dem(eq)]
|
|
58
|
+
if num is None or dem is None:
|
|
59
|
+
return eq
|
|
60
|
+
|
|
61
|
+
return lhospital(num, dem, 10,var)
|
|
62
|
+
def limit0(equation):
|
|
63
|
+
if equation.name == "f_ref":
|
|
64
|
+
return equation
|
|
65
|
+
eq2 = equation
|
|
66
|
+
g = ["f_limit", "f_limitpinf", "f_limitninf"]
|
|
67
|
+
if eq2.name in g and contain(eq2.children[0], eq2.children[1]):
|
|
68
|
+
equation = eq2.children[0]
|
|
69
|
+
wrt = eq2.children[1]
|
|
70
|
+
lst = factor_generation(equation)
|
|
71
|
+
|
|
72
|
+
lst_const = [item for item in lst if not contain(item, wrt)]
|
|
73
|
+
if lst_const != []:
|
|
74
|
+
|
|
75
|
+
equation = product([item for item in lst if contain(item, wrt)]).copy_tree()
|
|
76
|
+
const = product(lst_const)
|
|
77
|
+
const = simplify(const)
|
|
78
|
+
|
|
79
|
+
if not contain(const, tree_form("s_i")):
|
|
80
|
+
|
|
81
|
+
return limit0(TreeNode(equation.name,[equation, wrt])) *const
|
|
82
|
+
equation = eq2
|
|
83
|
+
return TreeNode(equation.name, [limit0(child) for child in equation.children])
|
|
84
|
+
def limit2(eq):
|
|
85
|
+
g = ["f_limit", "f_limitpinf", "f_limitninf"]
|
|
86
|
+
if eq.name in g and eq.children[0].name == "f_add":
|
|
87
|
+
eq = summation([TreeNode(eq.name, [child, eq.children[1]]) for child in eq.children[0].children])
|
|
88
|
+
return TreeNode(eq.name, [limit2(child) for child in eq.children])
|
|
89
|
+
def limit1(eq):
|
|
90
|
+
if eq.name == "f_limit":
|
|
91
|
+
a, b = limit(eq.children[0], eq.children[1].name)
|
|
92
|
+
if b:
|
|
93
|
+
return a
|
|
94
|
+
else:
|
|
95
|
+
return TreeNode(eq.name, [a, eq.children[1]])
|
|
96
|
+
return TreeNode(eq.name, [limit1(child) for child in eq.children])
|
|
97
|
+
def fxinf(eq):
|
|
98
|
+
if eq is None:
|
|
99
|
+
return None
|
|
100
|
+
if eq.name == "f_add":
|
|
101
|
+
if tree_form("s_inf") in eq.children and -tree_form("s_inf") in eq.children:
|
|
102
|
+
return None
|
|
103
|
+
if tree_form("s_inf") in eq.children:
|
|
104
|
+
return tree_form("s_inf")
|
|
105
|
+
if -tree_form("s_inf") in eq.children:
|
|
106
|
+
return -tree_form("s_inf")
|
|
107
|
+
if eq.name == "f_mul":
|
|
108
|
+
lst = factor_generation(eq)
|
|
109
|
+
if tree_form("s_inf") in lst:
|
|
110
|
+
eq = TreeNode(eq.name, [dowhile(child, fxinf) for child in eq.children])
|
|
111
|
+
if None in eq.children:
|
|
112
|
+
return None
|
|
113
|
+
lst = factor_generation(eq)
|
|
114
|
+
if tree_form("d_0") in lst:
|
|
115
|
+
return tree_form("d_0")
|
|
116
|
+
lst2 = [item for item in lst if "v_" in str_form(item)]
|
|
117
|
+
sign = True
|
|
118
|
+
if len([item for item in lst if "v_" not in str_form(item) and not contain(item, tree_form("s_inf")) and compute(item)<0]) % 2==1:
|
|
119
|
+
sign = False
|
|
120
|
+
if lst2 == []:
|
|
121
|
+
if sign:
|
|
122
|
+
return tree_form("s_inf")
|
|
123
|
+
else:
|
|
124
|
+
return -tree_form("s_inf")
|
|
125
|
+
if eq.name == "f_pow":
|
|
126
|
+
if "v_" not in str_form(eq.children[0]) and not contain(eq.children[0], tree_form("s_inf")) and compute(eq.children[0])>0:
|
|
127
|
+
if eq.children[1] == -tree_form("s_inf"):
|
|
128
|
+
return tree_form("d_0")
|
|
129
|
+
|
|
130
|
+
eq = TreeNode(eq.name, [fxinf(child) for child in eq.children])
|
|
131
|
+
if None in eq.children:
|
|
132
|
+
return None
|
|
133
|
+
return eq
|
|
134
|
+
def limit3(eq):
|
|
135
|
+
|
|
136
|
+
if eq.name == "f_limitpinf":
|
|
137
|
+
if not contain(eq, eq.children[1]):
|
|
138
|
+
return eq.children[0]
|
|
139
|
+
eq2 = replace(eq.children[0], eq.children[1], tree_form("s_inf"))
|
|
140
|
+
eq2 = dowhile(eq2, fxinf)
|
|
141
|
+
if not contain(eq2, tree_form("s_inf")) and not contain(eq2, eq.children[1]):
|
|
142
|
+
return simplify(eq2)
|
|
143
|
+
return TreeNode(eq.name, [limit3(child) for child in eq.children])
|
|
144
|
+
|
|
145
|
+
def limit(equation, var="v_0"):
|
|
146
|
+
|
|
147
|
+
eq2 = dowhile(replace(equation, tree_form(var), tree_form("d_0")), lambda x: trig0(simplify(x)))
|
|
148
|
+
if eq2 is not None and not contain(equation, tree_form(var)):
|
|
149
|
+
return eq2, True
|
|
150
|
+
|
|
151
|
+
equation = lhospital2(equation, var)
|
|
152
|
+
equation = simplify(expand(simplify(equation)))
|
|
153
|
+
if not contain(equation, tree_form(var)):
|
|
154
|
+
return equation, True
|
|
155
|
+
|
|
156
|
+
return equation, False
|