mathai 0.4.4__tar.gz → 0.4.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mathai-0.4.4 → mathai-0.4.6}/PKG-INFO +1 -1
- {mathai-0.4.4 → mathai-0.4.6}/mathai/__init__.py +5 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/base.py +1 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/factor.py +88 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/integrate.py +1 -2
- mathai-0.4.6/mathai/ode.py +124 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/simplify.py +1 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/trig.py +31 -28
- {mathai-0.4.4 → mathai-0.4.6}/mathai.egg-info/PKG-INFO +1 -1
- {mathai-0.4.4 → mathai-0.4.6}/mathai.egg-info/SOURCES.txt +1 -0
- {mathai-0.4.4 → mathai-0.4.6}/setup.py +1 -1
- {mathai-0.4.4 → mathai-0.4.6}/README.md +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/apart.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/console.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/diff.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/expand.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/fraction.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/inverse.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/limit.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/linear.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/logic.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/parser.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/printeq.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/structure.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/tool.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai/univariate_inequality.py +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai.egg-info/dependency_links.txt +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai.egg-info/requires.txt +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/mathai.egg-info/top_level.txt +0 -0
- {mathai-0.4.4 → mathai-0.4.6}/setup.cfg +0 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
from .ode import diffsolve as ode_solve
|
|
2
|
+
from .ode import diffsolve_sep as ode_shift_term
|
|
3
|
+
|
|
1
4
|
from .expand import expand
|
|
2
5
|
|
|
3
6
|
from .parser import parse
|
|
@@ -20,6 +23,8 @@ from .diff import diff
|
|
|
20
23
|
|
|
21
24
|
from .factor import factor as factor1
|
|
22
25
|
from .factor import factor2
|
|
26
|
+
from .factor import rationalize_sqrt as rationalize
|
|
27
|
+
from .factor import merge_sqrt
|
|
23
28
|
from .factor import factorconst as factor0
|
|
24
29
|
|
|
25
30
|
from .fraction import fraction
|
|
@@ -69,6 +69,93 @@ def _factorconst(eq):
|
|
|
69
69
|
if n != 1:
|
|
70
70
|
return tree_form("d_"+str(n))*eq
|
|
71
71
|
return TreeNode(eq.name, [factorconst(child) for child in eq.children])
|
|
72
|
+
|
|
73
|
+
def _merge_sqrt(eq):
|
|
74
|
+
lst= []
|
|
75
|
+
eq2 = []
|
|
76
|
+
for child in factor_generation(eq):
|
|
77
|
+
if frac(child) is not None and frac(child).denominator==1:
|
|
78
|
+
if frac(child)>0:
|
|
79
|
+
eq2.append(child**2)
|
|
80
|
+
elif frac(child)!=-1:
|
|
81
|
+
eq2.append((-child)**2)
|
|
82
|
+
lst.append(tree_form("d_-1"))
|
|
83
|
+
else:
|
|
84
|
+
lst.append(tree_form("d_-1"))
|
|
85
|
+
elif child.name == "f_pow" and frac(child.children[1]) == Fraction(1,2):
|
|
86
|
+
eq2.append(child.children[0])
|
|
87
|
+
else:
|
|
88
|
+
lst.append(child)
|
|
89
|
+
|
|
90
|
+
if len(eq2)>1:
|
|
91
|
+
if lst == []:
|
|
92
|
+
lst= [tree_form("d_1")]
|
|
93
|
+
return simplify(product(eq2)**(tree_form("d_2")**-1)*product(lst))
|
|
94
|
+
return TreeNode(eq.name, [_merge_sqrt(child) for child in eq.children])
|
|
95
|
+
def sqrt_to_a_sqrt_b(n):
|
|
96
|
+
if n == 0:
|
|
97
|
+
return 0, 0
|
|
98
|
+
sign = 1
|
|
99
|
+
if n < 0:
|
|
100
|
+
sign = -1
|
|
101
|
+
m = -n
|
|
102
|
+
else:
|
|
103
|
+
m = n
|
|
104
|
+
|
|
105
|
+
a = 1
|
|
106
|
+
b = 1
|
|
107
|
+
p = 2
|
|
108
|
+
while p * p <= m:
|
|
109
|
+
exp = 0
|
|
110
|
+
while m % p == 0:
|
|
111
|
+
m //= p
|
|
112
|
+
exp += 1
|
|
113
|
+
if exp:
|
|
114
|
+
a *= p ** (exp // 2)
|
|
115
|
+
if exp % 2 == 1:
|
|
116
|
+
b *= p
|
|
117
|
+
p += 1 if p == 2 else 2
|
|
118
|
+
|
|
119
|
+
if m > 1:
|
|
120
|
+
b *= m
|
|
121
|
+
|
|
122
|
+
return sign * a, b
|
|
123
|
+
def merge_sqrt(eq):
|
|
124
|
+
def helper(eq):
|
|
125
|
+
if eq.name == "f_pow" and frac(eq.children[1]) == Fraction(1,2):
|
|
126
|
+
if eq.children[0].name[:2] == "d_":
|
|
127
|
+
n = int(eq.children[0].name[2:])
|
|
128
|
+
a, b =sqrt_to_a_sqrt_b(n)
|
|
129
|
+
return tree_form("d_"+str(b))**(tree_form("d_2")**-1)*tree_form("d_"+str(a))
|
|
130
|
+
return TreeNode(eq.name, [helper(child) for child in eq.children])
|
|
131
|
+
return helper(_merge_sqrt(eq))
|
|
132
|
+
def rationalize_sqrt(eq):
|
|
133
|
+
if eq.name== "f_pow" and frac(eq.children[1]) == Fraction(-1,2):
|
|
134
|
+
eq = eq.children[0]**(tree_form("d_2")**-1)/eq.children[0]
|
|
135
|
+
def term(eq):
|
|
136
|
+
if eq.name == "f_add":
|
|
137
|
+
output = []
|
|
138
|
+
for child in eq.children:
|
|
139
|
+
if any(child2.name == "f_pow" and frac(child2.children[1]) == Fraction(1,2) for child2 in factor_generation(child)):
|
|
140
|
+
output.append(simplify(-child))
|
|
141
|
+
else:
|
|
142
|
+
output.append(child)
|
|
143
|
+
return summation(output)
|
|
144
|
+
return None
|
|
145
|
+
n, d=num_dem(eq)
|
|
146
|
+
n,d=simplify(n), simplify(d)
|
|
147
|
+
|
|
148
|
+
if d != 1:
|
|
149
|
+
t = term(d)
|
|
150
|
+
if t is not None and t!=1:
|
|
151
|
+
|
|
152
|
+
n,d=simplify(expand(simplify(n*t))),simplify(expand(simplify(d*t)))
|
|
153
|
+
tmp= simplify(n/d)
|
|
154
|
+
|
|
155
|
+
tmp = _merge_sqrt(tmp)
|
|
156
|
+
|
|
157
|
+
return tmp
|
|
158
|
+
return TreeNode(eq.name, [rationalize_sqrt(child) for child in eq.children])
|
|
72
159
|
def factorconst(eq):
|
|
73
160
|
return simplify(_factorconst(eq))
|
|
74
161
|
def factor_quad_formula_init():
|
|
@@ -77,6 +164,7 @@ def factor_quad_formula_init():
|
|
|
77
164
|
formula_list = [[simplify(parse(y)) for y in x] for x in formula_list]
|
|
78
165
|
expr = [[parse("A"), parse("1")], [parse("B"), parse("0"), parse("1")], [parse("C"), parse("0")]]
|
|
79
166
|
return [formula_list, var, expr]
|
|
167
|
+
|
|
80
168
|
def factor_quar_formula_init():
|
|
81
169
|
var = ""
|
|
82
170
|
formula_list = [(f"(A^4+B*A^2+C)", f"(A^2 + sqrt(2*sqrt(C) - B)*A + sqrt(C))*(A^2 - sqrt(2*sqrt(C) - B)*A + sqrt(C))")]
|
|
@@ -367,7 +367,7 @@ def rm_const(equation):
|
|
|
367
367
|
if equation.name == "f_ref":
|
|
368
368
|
return equation
|
|
369
369
|
eq2 = equation
|
|
370
|
-
if eq2.name == "f_integrate":
|
|
370
|
+
if eq2.name == "f_integrate" and contain(eq2.children[0], eq2.children[1]):
|
|
371
371
|
equation = eq2.children[0]
|
|
372
372
|
wrt = eq2.children[1]
|
|
373
373
|
lst = factor_generation(equation)
|
|
@@ -407,4 +407,3 @@ def integrate_formula(equation):
|
|
|
407
407
|
|
|
408
408
|
return out
|
|
409
409
|
return TreeNode(eq2.name, [integrate_formula(child) for child in eq2.children])
|
|
410
|
-
|
|
@@ -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
|
|
@@ -82,7 +82,7 @@ def trig0(eq):
|
|
|
82
82
|
if any(isneg(item) for item in lst):
|
|
83
83
|
return -(eq.children[0]*-1).fx("sin")
|
|
84
84
|
out=single_pi(lst)
|
|
85
|
-
if out is not None:
|
|
85
|
+
if out is not None and tuple(out) in trig_sin_table.keys():
|
|
86
86
|
return trig_sin_table[tuple(out)]
|
|
87
87
|
|
|
88
88
|
if eq.name == "f_cos":
|
|
@@ -211,35 +211,38 @@ def trig4(eq, numer=True):
|
|
|
211
211
|
return TreeNode(eq.name, [trig4(child, False) if not numer or (eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]) < 0) else trig4(child, True) for child in eq.children])
|
|
212
212
|
|
|
213
213
|
def trig2(eq):
|
|
214
|
-
if
|
|
215
|
-
|
|
216
|
-
|
|
214
|
+
# Base case: if not an addition, recurse into children
|
|
215
|
+
if eq.name != "f_add":
|
|
216
|
+
return TreeNode(eq.name, [trig2(child) for child in eq.children])
|
|
217
|
+
|
|
218
|
+
# Try all pairs in the addition
|
|
219
|
+
for i, j in itertools.combinations(range(len(eq.children)), 2):
|
|
220
|
+
c1, c2 = eq.children[i], eq.children[j]
|
|
221
|
+
|
|
222
|
+
# Combine only sin/sin or cos/cos
|
|
223
|
+
if c1.name in ["f_sin", "f_cos"] and c2.name in ["f_sin", "f_cos"]:
|
|
224
|
+
A, B = c1.children[0], c2.children[0]
|
|
225
|
+
rest = [eq.children[k] for k in range(len(eq.children)) if k not in (i, j)]
|
|
226
|
+
rest_tree = summation(rest) if rest else tree_form("d_0")
|
|
217
227
|
|
|
218
|
-
|
|
219
|
-
if child1.name in ["f_sin", "f_cos"] and child2.name in ["f_sin", "f_cos"]:
|
|
220
|
-
a, b = child1.children[0], child2.children[0]
|
|
221
|
-
|
|
222
|
-
# Compute the rest of the sum
|
|
223
|
-
rest = [eq.children[i] for i in range(len(eq.children)) if i not in item]
|
|
224
|
-
if len(rest) == 0:
|
|
225
|
-
rest_tree = tree_form("d_0")
|
|
226
|
-
else:
|
|
227
|
-
rest_tree = summation(rest)
|
|
228
|
+
two = tree_form("d_2")
|
|
228
229
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
two = tree_form("d_2")
|
|
233
|
-
combined = two * ((a + b) / two).fx("sin") * ((a - b) / two).fx("cos")
|
|
234
|
-
elif child1.name == "f_cos" and child2.name == "f_cos":
|
|
235
|
-
# cos A + cos B = 2 cos((A+B)/2) cos((A-B)/2)
|
|
236
|
-
two = tree_form("d_2")
|
|
237
|
-
combined = two * ((a + b) / two).fx("cos") * ((a - b) / two).fx("cos")
|
|
238
|
-
else:
|
|
239
|
-
# sin A + cos B = sin A + cos B (leave unchanged, or implement formula if desired)
|
|
240
|
-
continue # skip for now, keep original
|
|
230
|
+
# sinA + sinB
|
|
231
|
+
if c1.name == "f_sin" and c2.name == "f_sin":
|
|
232
|
+
combined = two * ((A + B) / two).fx("sin") * ((A - B) / two).fx("cos")
|
|
241
233
|
|
|
242
|
-
|
|
234
|
+
# cosA + cosB
|
|
235
|
+
elif c1.name == "f_cos" and c2.name == "f_cos":
|
|
236
|
+
combined = two * ((A + B) / two).fx("cos") * ((A - B) / two).fx("cos")
|
|
243
237
|
|
|
244
|
-
|
|
238
|
+
# sinA + cosB (leave unchanged)
|
|
239
|
+
else:
|
|
240
|
+
continue
|
|
241
|
+
|
|
242
|
+
new_expr = rest_tree + combined
|
|
243
|
+
# Re-run trig2 in case there are more sin/cos sums to simplify
|
|
244
|
+
return trig2(new_expr)
|
|
245
|
+
|
|
246
|
+
# If no sin/cos pairs found, just recurse on children
|
|
245
247
|
return TreeNode(eq.name, [trig2(child) for child in eq.children])
|
|
248
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|