mathai 0.4.8__py3-none-any.whl → 0.7.2__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 +9 -8
- mathai/base.py +132 -34
- mathai/bivariate_inequality.py +317 -0
- mathai/diff.py +3 -3
- mathai/expand.py +159 -80
- mathai/factor.py +45 -21
- mathai/fraction.py +2 -2
- mathai/integrate.py +38 -19
- mathai/inverse.py +4 -4
- mathai/limit.py +94 -70
- mathai/linear.py +90 -81
- mathai/logic.py +7 -1
- mathai/matrix.py +228 -0
- mathai/parser.py +13 -7
- mathai/parsetab.py +61 -0
- mathai/printeq.py +12 -9
- mathai/simplify.py +511 -369
- mathai/structure.py +2 -2
- mathai/tool.py +2 -2
- mathai/trig.py +42 -25
- mathai/univariate_inequality.py +78 -30
- mathai-0.7.2.dist-info/METADATA +293 -0
- mathai-0.7.2.dist-info/RECORD +28 -0
- {mathai-0.4.8.dist-info → mathai-0.7.2.dist-info}/WHEEL +1 -1
- mathai-0.4.8.dist-info/METADATA +0 -234
- mathai-0.4.8.dist-info/RECORD +0 -25
- {mathai-0.4.8.dist-info → mathai-0.7.2.dist-info}/top_level.txt +0 -0
mathai/expand.py
CHANGED
|
@@ -1,96 +1,175 @@
|
|
|
1
|
-
import itertools
|
|
2
1
|
from .base import *
|
|
3
|
-
from .simplify import
|
|
2
|
+
from .simplify import simplify
|
|
3
|
+
import itertools
|
|
4
4
|
|
|
5
|
-
def
|
|
6
|
-
if
|
|
7
|
-
return
|
|
5
|
+
def eliminate_powers(node):
|
|
6
|
+
if not node.children:
|
|
7
|
+
return node
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
node.children = [eliminate_powers(c) for c in node.children]
|
|
10
|
+
|
|
11
|
+
if node.name == "f_pow":
|
|
12
|
+
base, exp = node.children
|
|
13
|
+
n = frac(exp)
|
|
14
|
+
|
|
15
|
+
# Only expand positive integer powers
|
|
16
|
+
if not (n and n.denominator == 1 and n.numerator > 1):
|
|
17
|
+
return node
|
|
18
|
+
|
|
19
|
+
n = n.numerator
|
|
20
|
+
|
|
21
|
+
# ---- Multinomial expansion ----
|
|
22
|
+
if base.name == "f_add":
|
|
23
|
+
terms = []
|
|
24
|
+
for combo in itertools.product(base.children, repeat=n):
|
|
25
|
+
prod = combo[0]
|
|
26
|
+
for c in combo[1:]:
|
|
27
|
+
prod = prod * c
|
|
28
|
+
terms.append(prod)
|
|
29
|
+
return simplify(TreeNode("f_add", terms))
|
|
30
|
+
|
|
31
|
+
# ---- Fallback: simple power ----
|
|
32
|
+
return TreeNode("f_mul", [base] * n)
|
|
33
|
+
|
|
34
|
+
return node
|
|
11
35
|
|
|
12
|
-
while stack:
|
|
13
|
-
node, stage = stack.pop()
|
|
14
|
-
node_id = id(node)
|
|
15
|
-
|
|
16
|
-
# Leaf node
|
|
17
|
-
if not node.children and stage == 0:
|
|
18
|
-
result_map[node_id] = TreeNode(node.name, [])
|
|
19
|
-
continue
|
|
20
|
-
|
|
21
|
-
if stage == 0:
|
|
22
|
-
# Stage 0: push node back for stage 1 after children
|
|
23
|
-
stack.append((node, 1))
|
|
24
|
-
# Push children to stack
|
|
25
|
-
for child in reversed(node.children):
|
|
26
|
-
if id(child) not in result_map:
|
|
27
|
-
stack.append((child, 0))
|
|
28
|
-
else:
|
|
29
|
-
# Stage 1: all children processed
|
|
30
|
-
children_expanded = [result_map[id(child)] for child in node.children]
|
|
31
36
|
|
|
32
|
-
# Only f_mul or f_pow need special expansion
|
|
33
|
-
if node.name in ["f_mul", "f_pow"]:
|
|
34
|
-
current_eq = TreeNode(node.name, children_expanded)
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
# =====================================================
|
|
39
|
+
# Phase 2: Single distributive rewrite (DEEPEST FIRST)
|
|
40
|
+
# =====================================================
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
def expand_once(node):
|
|
43
|
+
"""
|
|
44
|
+
Performs exactly ONE distributive expansion.
|
|
45
|
+
Deepest-first (post-order).
|
|
46
|
+
"""
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
# ---- recurse FIRST (this is the fix) ----
|
|
49
|
+
for i, c in enumerate(node.children):
|
|
50
|
+
new, changed = expand_once(c)
|
|
51
|
+
if changed:
|
|
52
|
+
node.children[i] = new
|
|
53
|
+
return node, True
|
|
45
54
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
# ---- now try expanding at this node ----
|
|
56
|
+
if node.name == "f_mul":
|
|
57
|
+
for i, child in enumerate(node.children):
|
|
58
|
+
if child.name == "f_add":
|
|
59
|
+
left = node.children[:i]
|
|
60
|
+
right = node.children[i+1:]
|
|
61
|
+
|
|
62
|
+
terms = []
|
|
63
|
+
for t in child.children:
|
|
64
|
+
prod = t
|
|
65
|
+
for r in right:
|
|
66
|
+
prod = prod * r
|
|
67
|
+
for l in reversed(left):
|
|
68
|
+
prod = l * prod
|
|
69
|
+
terms.append(prod)
|
|
70
|
+
|
|
71
|
+
return TreeNode("f_add", terms), True
|
|
72
|
+
|
|
73
|
+
return node, False
|
|
74
|
+
|
|
75
|
+
def _expand2(equation):
|
|
76
|
+
"""Iterative version of _expand without recursion."""
|
|
77
|
+
# Stack: (node, child_index, partially_processed_children)
|
|
78
|
+
stack = [(equation, 0, [])]
|
|
79
|
+
|
|
80
|
+
while stack:
|
|
81
|
+
node, child_index, processed_children = stack.pop()
|
|
82
|
+
|
|
83
|
+
# If all children are processed
|
|
84
|
+
if child_index >= len(node.children):
|
|
85
|
+
# Replace children with processed versions
|
|
86
|
+
node.children = processed_children
|
|
87
|
+
|
|
88
|
+
# === Handle f_pow ===
|
|
89
|
+
if node.name == "f_pow":
|
|
90
|
+
n = frac(node.children[1])
|
|
91
|
+
if n is not None and n.denominator == 1 and n.numerator > 1:
|
|
92
|
+
# Convert power to repeated multiplication
|
|
93
|
+
power_children = [node.children[0] for _ in range(n.numerator)]
|
|
94
|
+
new_node = TreeNode("f_mul", power_children)
|
|
95
|
+
# Flatten tree
|
|
96
|
+
node = flatten_tree(new_node)
|
|
97
|
+
# Push it back for further processing
|
|
98
|
+
stack.append((node, 0, []))
|
|
99
|
+
continue
|
|
100
|
+
|
|
101
|
+
# === Handle f_mul ===
|
|
102
|
+
elif node.name == "f_mul":
|
|
103
|
+
# Separate lone children and bracket children
|
|
104
|
+
lone_children = tree_form("d_1")
|
|
105
|
+
bracket_children = []
|
|
106
|
+
|
|
107
|
+
# Iterate in reverse (like original)
|
|
108
|
+
for child in reversed(node.children):
|
|
49
109
|
if child.name == "f_add":
|
|
50
|
-
|
|
51
|
-
|
|
110
|
+
bracket_children.append(child)
|
|
111
|
+
elif child.name == "f_pow" and child.children[0].name == "f_add":
|
|
112
|
+
n = frac(child.children[1])
|
|
113
|
+
if n is not None and n.denominator == 1 and n.numerator > 1:
|
|
114
|
+
for _ in range(n.numerator):
|
|
115
|
+
bracket_children.append(child.children[0])
|
|
52
116
|
else:
|
|
53
|
-
|
|
117
|
+
lone_children = lone_children * child
|
|
54
118
|
else:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if isinstance(item, list) and item == []:
|
|
68
|
-
continue
|
|
69
|
-
if isinstance(item, list):
|
|
70
|
-
flat_list.extend(flatten(item))
|
|
119
|
+
lone_children = lone_children * child
|
|
120
|
+
|
|
121
|
+
lone_children = simplify(lone_children)
|
|
122
|
+
|
|
123
|
+
# Distribute bracket children over lone children iteratively
|
|
124
|
+
while bracket_children:
|
|
125
|
+
tmp = tree_form("d_0")
|
|
126
|
+
bracket = bracket_children.pop(0)
|
|
127
|
+
for bc in bracket.children:
|
|
128
|
+
if lone_children.name == "f_add":
|
|
129
|
+
for lc in lone_children.children:
|
|
130
|
+
tmp = tmp + bc * lc
|
|
71
131
|
else:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
add = simplify(add)
|
|
84
|
-
current_eq = simplify(add)
|
|
85
|
-
else:
|
|
86
|
-
current_eq = simplify(current_eq)
|
|
87
|
-
|
|
88
|
-
# Store expanded result
|
|
89
|
-
result_map[node_id] = current_eq
|
|
132
|
+
tmp = tmp + bc * lone_children
|
|
133
|
+
# Simplify after each distribution
|
|
134
|
+
lone_children = flatten_tree(simplify(tmp))
|
|
135
|
+
|
|
136
|
+
node = lone_children
|
|
137
|
+
|
|
138
|
+
# === Return node to parent ===
|
|
139
|
+
if stack:
|
|
140
|
+
parent, idx, parent_children = stack.pop()
|
|
141
|
+
parent_children.append(node)
|
|
142
|
+
stack.append((parent, idx + 1, parent_children))
|
|
90
143
|
else:
|
|
91
|
-
#
|
|
92
|
-
|
|
144
|
+
# Root node fully expanded
|
|
145
|
+
return node
|
|
93
146
|
|
|
94
|
-
|
|
95
|
-
|
|
147
|
+
else:
|
|
148
|
+
# Push current node back for next child
|
|
149
|
+
stack.append((node, child_index, processed_children))
|
|
150
|
+
# Push the child to process next
|
|
151
|
+
child = flatten_tree(node.children[child_index])
|
|
152
|
+
stack.append((child, 0, []))
|
|
96
153
|
|
|
154
|
+
# =====================================================
|
|
155
|
+
# Phase 3: Global fixed-point driver
|
|
156
|
+
# =====================================================
|
|
157
|
+
|
|
158
|
+
def expand(eq):
|
|
159
|
+
orig = TreeNode.matmul
|
|
160
|
+
if TreeNode.matmul is None:
|
|
161
|
+
return _expand2(eq)
|
|
162
|
+
eq = simplify(eq)
|
|
163
|
+
if TreeNode.matmul is not None:
|
|
164
|
+
TreeNode.matmul = True
|
|
165
|
+
eq = tree_form(str_form(eq).replace("f_wmul", "f_mul"))
|
|
166
|
+
eq = flatten_tree(eq)
|
|
167
|
+
eq = eliminate_powers(eq)
|
|
168
|
+
while True:
|
|
169
|
+
eq = flatten_tree(eq)
|
|
170
|
+
eq, changed = expand_once(eq)
|
|
171
|
+
if not changed:
|
|
172
|
+
break
|
|
173
|
+
eq =simplify(eq)
|
|
174
|
+
TreeNode.matmul = orig
|
|
175
|
+
return eq
|
mathai/factor.py
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import itertools
|
|
2
|
+
from .trig import trig0
|
|
2
3
|
from .parser import parse
|
|
3
4
|
from .structure import transform_formula
|
|
4
5
|
from .base import *
|
|
5
|
-
from .simplify import simplify
|
|
6
|
+
from .simplify import simplify
|
|
6
7
|
from .expand import expand
|
|
7
8
|
import math
|
|
8
9
|
from .tool import poly
|
|
10
|
+
from .fraction import fraction
|
|
9
11
|
|
|
10
12
|
from collections import Counter
|
|
11
13
|
def multiset_intersection(*lists):
|
|
@@ -31,8 +33,8 @@ def term_common2(eq):
|
|
|
31
33
|
return product(s)*summation([product(subtract_sublist(factor_generation(child), s)) for child in eq.children])
|
|
32
34
|
def term_common(eq):
|
|
33
35
|
if eq.name == "f_add":
|
|
34
|
-
return
|
|
35
|
-
return
|
|
36
|
+
return simplify(term_common2(eq))
|
|
37
|
+
return simplify(product([term_common2(item) for item in factor_generation(eq)]))
|
|
36
38
|
def take_common(eq):
|
|
37
39
|
if eq.name == "f_add":
|
|
38
40
|
eq = term_common(eq)
|
|
@@ -42,7 +44,7 @@ def take_common(eq):
|
|
|
42
44
|
eq2 = summation([item2 for index, item2 in enumerate(eq.children) if index in item])
|
|
43
45
|
eq2 = term_common(eq2)
|
|
44
46
|
if eq2.name == "f_mul":
|
|
45
|
-
return take_common(
|
|
47
|
+
return take_common(simplify(summation([item2 for index, item2 in enumerate(eq.children) if index not in item]) + eq2))
|
|
46
48
|
break
|
|
47
49
|
return eq
|
|
48
50
|
return term_common(eq)
|
|
@@ -54,10 +56,13 @@ def _factorconst(eq):
|
|
|
54
56
|
def hcf_list(numbers):
|
|
55
57
|
if not numbers:
|
|
56
58
|
return None # empty list
|
|
59
|
+
n = 1
|
|
60
|
+
if math.prod(numbers) < 0:
|
|
61
|
+
n = -1
|
|
57
62
|
hcf = numbers[0]
|
|
58
63
|
for num in numbers[1:]:
|
|
59
|
-
hcf = math.gcd(hcf, num)
|
|
60
|
-
return hcf
|
|
64
|
+
hcf = math.gcd(hcf, abs(num))
|
|
65
|
+
return hcf*n
|
|
61
66
|
def extractnum(eq):
|
|
62
67
|
lst = factor_generation(eq)
|
|
63
68
|
for item in lst:
|
|
@@ -169,9 +174,11 @@ def factor_quar_formula_init():
|
|
|
169
174
|
return [formula_list, var, expr]
|
|
170
175
|
|
|
171
176
|
formula_gen9 = factor_quar_formula_init()
|
|
177
|
+
|
|
172
178
|
def factor_helper(equation, complexnum, power=2):
|
|
173
179
|
global formula_gen9
|
|
174
|
-
|
|
180
|
+
if equation.name in ["f_or", "f_and", "f_not", "f_eq", "f_gt", "f_lt", "f_ge", "f_le"]:
|
|
181
|
+
return TreeNode(equation.name, [factor_helper(child, complexnum, power) for child in equation.children])
|
|
175
182
|
maxnum=1
|
|
176
183
|
alloclst = []
|
|
177
184
|
for i in range(0,26):
|
|
@@ -225,8 +232,8 @@ def factor_helper(equation, complexnum, power=2):
|
|
|
225
232
|
a, b, c = lst
|
|
226
233
|
x1 = (-b+(b**2 - 4*a*c)**(tree_form("d_2")**-1))/(2*a)
|
|
227
234
|
x2 = (-b-(b**2 - 4*a*c)**(tree_form("d_2")**-1))/(2*a)
|
|
228
|
-
x1 = simplify(x1)
|
|
229
|
-
x2 = simplify(x2)
|
|
235
|
+
x1 = expand(simplify(x1))
|
|
236
|
+
x2 = expand(simplify(x2))
|
|
230
237
|
eq2 = a*(tree_form(r)-x1)*(tree_form(r)-x2)
|
|
231
238
|
if not complexnum and (contain(x1, tree_form("s_i")) or contain(x2, tree_form("s_i"))):
|
|
232
239
|
success = False
|
|
@@ -236,14 +243,27 @@ def factor_helper(equation, complexnum, power=2):
|
|
|
236
243
|
p = C-(B**2)/3
|
|
237
244
|
q = 2*B**3/27-B*C/3+D
|
|
238
245
|
t = q**2/4+ p**3/27
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
246
|
+
|
|
247
|
+
if compute(t) > 0:
|
|
248
|
+
u = (-q/2+t**(tree_form("d_2")**-1))**(tree_form("d_3")**-1)
|
|
249
|
+
v = (-q/2-t**(tree_form("d_2")**-1))**(tree_form("d_3")**-1)
|
|
250
|
+
y1 = u+v
|
|
251
|
+
three = 3**(tree_form("d_2")**-1)
|
|
252
|
+
y2 = -(u+v)/2+tree_form("s_i")*three*(u-v)/2
|
|
253
|
+
y3 = -(u+v)/2-tree_form("s_i")*three*(u-v)/2
|
|
254
|
+
|
|
255
|
+
else:
|
|
256
|
+
ar = 2*(-p/3)**(tree_form("d_2")**-1)
|
|
257
|
+
phi = ((3*q/(2*p))*(-3/p)**(tree_form("d_2")**-1)).fx("arccos")
|
|
258
|
+
y1 = ar*(phi/3).fx("cos")
|
|
259
|
+
y2 = ar*((phi+2*tree_form("s_pi"))/3).fx("cos")
|
|
260
|
+
y3 = ar*((phi+4*tree_form("s_pi"))/3).fx("cos")
|
|
261
|
+
|
|
245
262
|
x1,x2,x3 = y1-B/3 , y2-B/3, y3-B/3
|
|
246
|
-
x1
|
|
263
|
+
x1 = simplify(trig0(simplify(x1)))
|
|
264
|
+
x2 = simplify(trig0(simplify(x2)))
|
|
265
|
+
x3 = simplify(trig0(simplify(x3)))
|
|
266
|
+
|
|
247
267
|
out2 = None
|
|
248
268
|
if not complexnum:
|
|
249
269
|
for item in itertools.combinations([x1,x2,x3],2):
|
|
@@ -251,7 +271,7 @@ def factor_helper(equation, complexnum, power=2):
|
|
|
251
271
|
out2 = (tree_form(r)-item[0])*(tree_form(r)-item[1])
|
|
252
272
|
break
|
|
253
273
|
if out2 is not None:
|
|
254
|
-
out2 = simplify(expand(simplify(out2)))
|
|
274
|
+
out2 = simplify(fraction(expand(simplify(out2))))
|
|
255
275
|
out3 = None
|
|
256
276
|
for item in [x1, x2, x3]:
|
|
257
277
|
if not contain(item,tree_form("s_i")):
|
|
@@ -265,17 +285,21 @@ def factor_helper(equation, complexnum, power=2):
|
|
|
265
285
|
equation = fx(eq2)
|
|
266
286
|
break
|
|
267
287
|
|
|
268
|
-
if power == 4:
|
|
288
|
+
if False and power == 4:
|
|
269
289
|
|
|
270
290
|
out = transform_formula(helper(equation), "v_0", formula_gen9[0], formula_gen9[1], formula_gen9[2])
|
|
271
291
|
|
|
272
292
|
if out is not None:
|
|
273
|
-
out = simplify(
|
|
293
|
+
out = simplify(out)
|
|
274
294
|
if out is not None and (complexnum or (not complexnum and not contain(out, tree_form("s_i")))):
|
|
275
295
|
return out
|
|
276
296
|
|
|
277
297
|
return TreeNode(equation.name, [factor_helper(child, complexnum, power) for child in equation.children])
|
|
278
298
|
def factor(equation):
|
|
279
|
-
return
|
|
299
|
+
return simplify(take_common2(simplify(equation)))
|
|
300
|
+
|
|
280
301
|
def factor2(equation, complexnum=False):
|
|
281
|
-
return
|
|
302
|
+
return simplify(factor_helper(simplify(equation), complexnum, 2))
|
|
303
|
+
|
|
304
|
+
def factor3(equation, complexnum=False):
|
|
305
|
+
return simplify(factor_helper(simplify(factor_helper(simplify(equation), complexnum, 2)), complexnum, 3))
|
mathai/fraction.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .base import *
|
|
2
|
-
from .simplify import
|
|
2
|
+
from .simplify import simplify
|
|
3
3
|
from .expand import expand
|
|
4
4
|
|
|
5
5
|
def fraction(eq):
|
|
@@ -100,4 +100,4 @@ def fraction(eq):
|
|
|
100
100
|
result_map[node] = TreeNode(node.name, children_processed)
|
|
101
101
|
|
|
102
102
|
# Final return
|
|
103
|
-
return
|
|
103
|
+
return simplify(result_map[eq])
|
mathai/integrate.py
CHANGED
|
@@ -3,7 +3,7 @@ from .parser import parse
|
|
|
3
3
|
import itertools
|
|
4
4
|
from .diff import diff
|
|
5
5
|
from .fraction import fraction
|
|
6
|
-
from .simplify import
|
|
6
|
+
from .simplify import simplify
|
|
7
7
|
from .expand import expand
|
|
8
8
|
from .base import *
|
|
9
9
|
from .printeq import printeq_str
|
|
@@ -79,8 +79,10 @@ def subs_heuristic(eq, var):
|
|
|
79
79
|
try_index = []
|
|
80
80
|
try_lst = []
|
|
81
81
|
def ref(eq):
|
|
82
|
+
'''
|
|
82
83
|
if eq.name in ["f_try", "f_ref"]:
|
|
83
84
|
return eq
|
|
85
|
+
'''
|
|
84
86
|
if eq.name == "f_integrate":
|
|
85
87
|
return TreeNode("f_try", [eq.fx("ref"), eq])
|
|
86
88
|
return TreeNode(eq.name, [ref(child) for child in eq.children])
|
|
@@ -98,12 +100,12 @@ def _solve_integrate(eq):
|
|
|
98
100
|
if eq.name == "f_ref":
|
|
99
101
|
return eq
|
|
100
102
|
if eq.name == "f_subs":
|
|
101
|
-
if
|
|
103
|
+
if all(item not in str_form(eq.children[0]) for item in ["f_integrate", "f_subs", "f_try"]):
|
|
102
104
|
return replace(eq.children[0], eq.children[1], eq.children[2])
|
|
103
105
|
|
|
104
106
|
if eq.name == "f_try":
|
|
105
107
|
for child in eq.children:
|
|
106
|
-
if
|
|
108
|
+
if all(item not in str_form(child) for item in ["f_integrate", "f_subs", "f_try"]):
|
|
107
109
|
return child
|
|
108
110
|
return TreeNode(eq.name, [_solve_integrate(child) for child in eq.children])
|
|
109
111
|
def handle_try(eq):
|
|
@@ -131,6 +133,7 @@ def inteq(eq):
|
|
|
131
133
|
break
|
|
132
134
|
if eq2 is None:
|
|
133
135
|
return eq
|
|
136
|
+
printeq(eq)
|
|
134
137
|
for child in eq.children:
|
|
135
138
|
if child.name == "f_ref":
|
|
136
139
|
output.append(child)
|
|
@@ -144,6 +147,8 @@ def inteq(eq):
|
|
|
144
147
|
output.append(out)
|
|
145
148
|
else:
|
|
146
149
|
output.append(child)
|
|
150
|
+
printeq(TreeNode("f_try", output))
|
|
151
|
+
print()
|
|
147
152
|
return TreeNode("f_try", output)
|
|
148
153
|
else:
|
|
149
154
|
return TreeNode(eq.name, [inteq(child) for child in eq.children])
|
|
@@ -164,7 +169,7 @@ def integrate_subs(equation, term, v1, v2):
|
|
|
164
169
|
orig = equation.copy_tree()
|
|
165
170
|
none = TreeNode("f_integrate",[orig, tree_form(v1)])
|
|
166
171
|
origv2 = copy.deepcopy(v2)
|
|
167
|
-
equation =
|
|
172
|
+
equation = simplify(equation)
|
|
168
173
|
eq = equation
|
|
169
174
|
termeq = term
|
|
170
175
|
t = inverse(copy.deepcopy(termeq), v1)
|
|
@@ -182,13 +187,13 @@ def integrate_subs(equation, term, v1, v2):
|
|
|
182
187
|
|
|
183
188
|
eq2 = replace(diff(g, v1), tree_form(v1), t)
|
|
184
189
|
equation = eq/eq2
|
|
185
|
-
equation =
|
|
190
|
+
equation = simplify(equation)
|
|
186
191
|
|
|
187
192
|
if v1 in str_form(equation):
|
|
188
193
|
|
|
189
194
|
return none
|
|
190
195
|
|
|
191
|
-
return TreeNode("f_subs", [TreeNode("f_integrate", [simplify(equation), tree_form(origv2)]),tree_form(origv2) ,g])
|
|
196
|
+
return dowhile(TreeNode("f_subs", [TreeNode("f_integrate", [simplify(equation), tree_form(origv2)]),tree_form(origv2) ,g]), trig0)
|
|
192
197
|
|
|
193
198
|
def integrate_subs_main(equation):
|
|
194
199
|
if equation.name == "f_ref":
|
|
@@ -330,13 +335,20 @@ def byparts(eq):
|
|
|
330
335
|
lst = factor_generation(eq)
|
|
331
336
|
if len(lst) == 3 and len(list(set(lst))) == 1:
|
|
332
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()]
|
|
333
344
|
if len(lst) == 1:
|
|
334
345
|
lst += [tree_form("d_1")]
|
|
335
346
|
if len(lst) == 2:
|
|
336
347
|
for i in range(2):
|
|
337
348
|
|
|
338
349
|
f, g = [lst[i], lst[1-i]]
|
|
339
|
-
|
|
350
|
+
if contain(f, tree_form("s_e")):
|
|
351
|
+
continue
|
|
340
352
|
out1 = TreeNode("f_integrate", [g.copy_tree(), wrt])
|
|
341
353
|
|
|
342
354
|
|
|
@@ -368,7 +380,6 @@ def integration_formula_init():
|
|
|
368
380
|
formula_list = [[simplify(parse(y)) for y in x] for x in formula_list]
|
|
369
381
|
expr = [[parse("A"), parse("1")], [parse("B"), parse("0")]]
|
|
370
382
|
return [formula_list, var, expr]
|
|
371
|
-
formula_gen = integration_formula_init()
|
|
372
383
|
def integration_formula_trig():
|
|
373
384
|
var = "x"
|
|
374
385
|
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}))")]
|
|
@@ -377,8 +388,12 @@ def integration_formula_trig():
|
|
|
377
388
|
[parse("C"), parse("0"), parse("1")], [parse("D"), parse("0"), parse("1")],\
|
|
378
389
|
[parse("E"), parse("0"), parse("1")], [parse("F"), parse("0"), parse("1")]]
|
|
379
390
|
return [formula_list, var, expr]
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
formula_gen = integration_formula_init()
|
|
380
394
|
formula_gen4 = integration_formula_trig()
|
|
381
395
|
|
|
396
|
+
|
|
382
397
|
def integration_formula_ex():
|
|
383
398
|
var = "x"
|
|
384
399
|
formula_list = [
|
|
@@ -399,6 +414,7 @@ def rm_const(equation):
|
|
|
399
414
|
if eq2.name == "f_integrate" and contain(eq2.children[0], eq2.children[1]):
|
|
400
415
|
equation = eq2.children[0]
|
|
401
416
|
wrt = eq2.children[1]
|
|
417
|
+
|
|
402
418
|
lst = factor_generation(equation)
|
|
403
419
|
|
|
404
420
|
lst_const = [item for item in lst if not contain(item, wrt)]
|
|
@@ -414,6 +430,10 @@ def rm_const(equation):
|
|
|
414
430
|
equation = eq2
|
|
415
431
|
return TreeNode(equation.name, [rm_const(child) for child in equation.children])
|
|
416
432
|
|
|
433
|
+
def shorten(eq):
|
|
434
|
+
if eq.name.startswith("d_"):
|
|
435
|
+
return tree_form("d_0")
|
|
436
|
+
return TreeNode(eq.name, [shorten(child) for child in eq.children])
|
|
417
437
|
def integrate_formula(equation):
|
|
418
438
|
if equation.name == "f_ref":
|
|
419
439
|
return equation.copy_tree()
|
|
@@ -429,15 +449,14 @@ def integrate_formula(equation):
|
|
|
429
449
|
if out is not None:
|
|
430
450
|
|
|
431
451
|
return out
|
|
432
|
-
expr_str = str_form(integrand)
|
|
433
|
-
if
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
return out
|
|
452
|
+
expr_str = str_form(shorten(integrand))
|
|
453
|
+
if len(expr_str) < 30:
|
|
454
|
+
if expr_str.count("f_sin") + expr_str.count("f_cos") > 2:
|
|
455
|
+
out = transform_formula(integrand, wrt.name, formula_gen4[0], formula_gen4[1], formula_gen4[2])
|
|
456
|
+
if out is not None:
|
|
457
|
+
return out
|
|
458
|
+
if "f_cos" in expr_str and contain(integrand, tree_form("s_e")):
|
|
459
|
+
out = transform_formula(integrand, wrt.name, formula_gen11[0], formula_gen11[1], formula_gen11[2])
|
|
460
|
+
if out is not None:
|
|
461
|
+
return out
|
|
443
462
|
return TreeNode(eq2.name, [integrate_formula(child) for child in eq2.children])
|
mathai/inverse.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from .base import *
|
|
2
|
-
from .simplify import
|
|
2
|
+
from .simplify import simplify
|
|
3
3
|
from .expand import expand
|
|
4
4
|
def inverse(rhs,term, sign=None):
|
|
5
5
|
term = tree_form(term)
|
|
@@ -9,7 +9,7 @@ def inverse(rhs,term, sign=None):
|
|
|
9
9
|
while not rhs==term:
|
|
10
10
|
if rhs.name == "f_add":
|
|
11
11
|
if all(term in factor_generation(child) for child in rhs.children):
|
|
12
|
-
newrhs =
|
|
12
|
+
newrhs = simplify(expand(rhs*term**-1))
|
|
13
13
|
if not contain(newrhs, term):
|
|
14
14
|
rhs = term * newrhs
|
|
15
15
|
else:
|
|
@@ -61,5 +61,5 @@ def inverse(rhs,term, sign=None):
|
|
|
61
61
|
if count == 0:
|
|
62
62
|
return None
|
|
63
63
|
if sign is None:
|
|
64
|
-
return
|
|
65
|
-
return
|
|
64
|
+
return simplify(lhs)
|
|
65
|
+
return simplify(lhs), sign
|