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/linear.py
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from .inverse import inverse
|
|
2
|
+
import itertools
|
|
3
|
+
from .diff import diff
|
|
4
|
+
from .simplify import simplify
|
|
5
|
+
from .fraction import fraction
|
|
6
|
+
from .expand import expand
|
|
7
|
+
from .base import *
|
|
8
|
+
from .factor import factorconst
|
|
9
|
+
from .tool import poly
|
|
10
|
+
def ss(eq):
|
|
11
|
+
return dowhile(eq, lambda x: fraction(expand(simplify(x))))
|
|
12
|
+
def rref(matrix):
|
|
13
|
+
rows, cols = len(matrix), len(matrix[0])
|
|
14
|
+
lead = 0
|
|
15
|
+
for r in range(rows):
|
|
16
|
+
if lead >= cols:
|
|
17
|
+
return matrix
|
|
18
|
+
i = r
|
|
19
|
+
while ss(matrix[i][lead]) == tree_form("d_0"):
|
|
20
|
+
i += 1
|
|
21
|
+
if i == rows:
|
|
22
|
+
i = r
|
|
23
|
+
lead += 1
|
|
24
|
+
if lead == cols:
|
|
25
|
+
return matrix
|
|
26
|
+
matrix[i], matrix[r] = matrix[r], matrix[i]
|
|
27
|
+
lv = matrix[r][lead]
|
|
28
|
+
matrix[r] = [ss(m / lv) for m in matrix[r]]
|
|
29
|
+
for i in range(rows):
|
|
30
|
+
if i != r:
|
|
31
|
+
lv = matrix[i][lead]
|
|
32
|
+
matrix[i] = [ss(m - lv * n) for m, n in zip(matrix[i], matrix[r])]
|
|
33
|
+
lead += 1
|
|
34
|
+
return matrix
|
|
35
|
+
def islinear(eq, fxconst):
|
|
36
|
+
eq =simplify(eq)
|
|
37
|
+
if all(fxconst(tree_form(item)) and poly(eq, item) is not None and len(poly(eq, item)) <= 2 for item in vlist(eq)):
|
|
38
|
+
return True
|
|
39
|
+
return False
|
|
40
|
+
def linear(eqlist, fxconst):
|
|
41
|
+
orig = [item.copy_tree() for item in eqlist]
|
|
42
|
+
#eqlist = [eq for eq in eqlist if fxconst(eq)]
|
|
43
|
+
|
|
44
|
+
if eqlist == [] or not all(islinear(eq, fxconst) for eq in eqlist):
|
|
45
|
+
return None
|
|
46
|
+
#return TreeNode("f_and", [TreeNode("f_eq", [x, tree_form("d_0")]) for x in orig])
|
|
47
|
+
vl = []
|
|
48
|
+
def varlist(eq, fxconst):
|
|
49
|
+
nonlocal vl
|
|
50
|
+
if eq.name[:2] == "v_" and fxconst(eq):
|
|
51
|
+
vl.append(eq.name)
|
|
52
|
+
for child in eq.children:
|
|
53
|
+
varlist(child, fxconst)
|
|
54
|
+
for eq in eqlist:
|
|
55
|
+
varlist(eq, fxconst)
|
|
56
|
+
vl = list(set(vl))
|
|
57
|
+
|
|
58
|
+
if len(vl) > len(eqlist):
|
|
59
|
+
return TreeNode("f_and", [TreeNode("f_eq", [x, tree_form("d_0")]) for x in eqlist])
|
|
60
|
+
m = []
|
|
61
|
+
for eq in eqlist:
|
|
62
|
+
s = copy.deepcopy(eq)
|
|
63
|
+
row = []
|
|
64
|
+
for v in vl:
|
|
65
|
+
row.append(diff(eq, v))
|
|
66
|
+
s = replace(s, tree_form(v), tree_form("d_0"))
|
|
67
|
+
row.append(s)
|
|
68
|
+
m.append(row)
|
|
69
|
+
for i in range(len(m)):
|
|
70
|
+
for j in range(len(m[i])):
|
|
71
|
+
m[i][j] = simplify(expand(m[i][j]))
|
|
72
|
+
|
|
73
|
+
m = rref(m)
|
|
74
|
+
|
|
75
|
+
for i in range(len(m)):
|
|
76
|
+
for j in range(len(m[i])):
|
|
77
|
+
m[i][j] = fraction(m[i][j])
|
|
78
|
+
|
|
79
|
+
output = []
|
|
80
|
+
for index, row in enumerate(m):
|
|
81
|
+
if not all(item == 0 for item in row[:-1]):
|
|
82
|
+
output.append(summation([tree_form(vl[index2])*coeff for index2, coeff in enumerate(row[:-1])])+row[-1])
|
|
83
|
+
elif row[-1] != 0:
|
|
84
|
+
return tree_form("s_false")
|
|
85
|
+
if len(output) == 1:
|
|
86
|
+
return TreeNode("f_eq", [output[0], tree_form("d_0")])
|
|
87
|
+
if len(output) == 0:
|
|
88
|
+
return tree_form("s_false")
|
|
89
|
+
return TreeNode("f_and", [TreeNode("f_eq", [x, tree_form("d_0")]) for x in output])
|
|
90
|
+
def order_collinear_indices(points, idx):
|
|
91
|
+
"""
|
|
92
|
+
Arrange a subset of collinear points (given by indices) along their line.
|
|
93
|
+
|
|
94
|
+
points: list of (x, y) tuples
|
|
95
|
+
idx: list of indices referring to points
|
|
96
|
+
Returns: list of indices sorted along the line
|
|
97
|
+
"""
|
|
98
|
+
if len(idx) <= 1:
|
|
99
|
+
return idx[:]
|
|
100
|
+
|
|
101
|
+
# Take first two points from the subset to define the line
|
|
102
|
+
p0, p1 = points[idx[0]], points[idx[1]]
|
|
103
|
+
dx, dy = p1[0] - p0[0], p1[1] - p0[1]
|
|
104
|
+
|
|
105
|
+
# Projection factor for sorting
|
|
106
|
+
def projection_factor(i):
|
|
107
|
+
vx, vy = points[i][0] - p0[0], points[i][1] - p0[1]
|
|
108
|
+
return compute((vx * dx + vy * dy) / (dx**2 + dy**2))
|
|
109
|
+
|
|
110
|
+
# Sort indices by projection
|
|
111
|
+
sorted_idx = sorted(idx, key=projection_factor)
|
|
112
|
+
return list(sorted_idx)
|
|
113
|
+
def linear_or(eq):
|
|
114
|
+
eqlst =[]
|
|
115
|
+
if eq.name != "f_or":
|
|
116
|
+
eqlst = [eq]
|
|
117
|
+
else:
|
|
118
|
+
eqlst = eq.children
|
|
119
|
+
v = vlist(eq)
|
|
120
|
+
p = []
|
|
121
|
+
line = {}
|
|
122
|
+
for i in range(len(eqlst)):
|
|
123
|
+
line[i] = []
|
|
124
|
+
for item in itertools.combinations(enumerate(eqlst), 2):
|
|
125
|
+
x, y = item[0][0], item[1][0]
|
|
126
|
+
item = [item[0][1], item[1][1]]
|
|
127
|
+
|
|
128
|
+
out = linear_solve(TreeNode("f_and", list(item)))
|
|
129
|
+
|
|
130
|
+
if out is None:
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
if out.name == "f_and" and all(len(vlist(child)) == 1 for child in out.children) and set(vlist(out)) == set(v) and all(len(vlist(simplify(child))) >0 for child in out.children):
|
|
134
|
+
t = {}
|
|
135
|
+
for child in out.children:
|
|
136
|
+
t[v.index(vlist(child)[0])] = simplify(inverse(child.children[0], vlist(child)[0]))
|
|
137
|
+
t2 = []
|
|
138
|
+
for key in sorted(t.keys()):
|
|
139
|
+
t2.append(t[key])
|
|
140
|
+
t2 = tuple(t2)
|
|
141
|
+
if t2 not in p:
|
|
142
|
+
p.append(t2)
|
|
143
|
+
line[x] += [p.index(t2)]
|
|
144
|
+
line[y] += [p.index(t2)]
|
|
145
|
+
line2 = []
|
|
146
|
+
for key in sorted(line.keys()):
|
|
147
|
+
line2.append(order_collinear_indices(p, list(set(line[key]))))
|
|
148
|
+
|
|
149
|
+
return v, p, line2, eqlst
|
|
150
|
+
def linear_solve(eq, lst=None):
|
|
151
|
+
eq = simplify(eq)
|
|
152
|
+
eqlist = []
|
|
153
|
+
if eq.name =="f_and" and all(child.name == "f_eq" and child.children[1] == 0 for child in eq.children):
|
|
154
|
+
|
|
155
|
+
eqlist = [child.children[0] for child in eq.children]
|
|
156
|
+
else:
|
|
157
|
+
return eq
|
|
158
|
+
out = None
|
|
159
|
+
if lst is None:
|
|
160
|
+
out = linear(copy.deepcopy(eqlist), lambda x: "v_" in str_form(x))
|
|
161
|
+
else:
|
|
162
|
+
out = linear(copy.deepcopy(eqlist), lambda x: any(contain(x, item) for item in lst))
|
|
163
|
+
if out is None:
|
|
164
|
+
return None
|
|
165
|
+
return simplify(out)
|
mathai/logic.py
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
from .base import *
|
|
3
|
+
def c(eq):
|
|
4
|
+
eq = logic1(eq)
|
|
5
|
+
eq = dowhile(eq, logic0)
|
|
6
|
+
eq = dowhile(eq, logic2)
|
|
7
|
+
return eq
|
|
8
|
+
def logic_n(eq):
|
|
9
|
+
return dowhile(eq, c)
|
|
10
|
+
def logic0(eq):
|
|
11
|
+
if eq.children is None or len(eq.children)==0:
|
|
12
|
+
return eq
|
|
13
|
+
if eq.name in ["f_eq", "f_lt", "f_gt" "f_ge"] and eq.children[1].name[:2]=="d_" and eq.children[0].name[:2]=="d_":
|
|
14
|
+
a, b = int(eq.children[0].name[2:]), int(eq.children[1].name[2:])
|
|
15
|
+
if eq.name == "f_eq":
|
|
16
|
+
return tree_form("s_true") if a==b else tree_form("s_false")
|
|
17
|
+
if eq.name == "f_ge":
|
|
18
|
+
return tree_form("s_true") if a>=b else tree_form("s_false")
|
|
19
|
+
if eq.name == "f_lt":
|
|
20
|
+
return tree_form("s_true") if a < b else tree_form("s_false")
|
|
21
|
+
if eq.name == "f_ge":
|
|
22
|
+
return TreeNode("f_gt", eq.children) | TreeNode("f_eq", eq.children)
|
|
23
|
+
|
|
24
|
+
if eq.name == "f_gt":
|
|
25
|
+
return TreeNode("f_lt", eq.children).fx("not") & TreeNode("f_eq", eq.children).fx("not")
|
|
26
|
+
|
|
27
|
+
if eq.name == "f_le":
|
|
28
|
+
return TreeNode("f_lt", eq.children) | TreeNode("f_eq", eq.children)
|
|
29
|
+
return TreeNode(eq.name, [logic0(child) for child in eq.children])
|
|
30
|
+
def logic3(eq):
|
|
31
|
+
if eq.name == "f_forall" and eq.children[1] in [tree_form("s_true"), tree_form("s_false")]:
|
|
32
|
+
return eq.children[1]
|
|
33
|
+
if eq.name == "f_not" and eq.children[0].name == "f_exist":
|
|
34
|
+
return TreeNode("f_forall", [eq.children[0].children[0], eq.children[0].children[1].fx("not")])
|
|
35
|
+
if eq.name == "f_exist" and eq.children[1].name == "f_or":
|
|
36
|
+
return TreeNode("f_or", [TreeNode("f_exist", [eq.children[0], child]) for child in eq.children[1].children])
|
|
37
|
+
if eq.name == "f_forall" and eq.children[1].name == "f_and":
|
|
38
|
+
return TreeNode("f_and", [TreeNode("f_forall", [eq.children[0], child]) for child in eq.children[1].children])
|
|
39
|
+
if eq.name == "f_exist":
|
|
40
|
+
return TreeNode("f_forall", [eq.children[0], eq.children[1].fx("not")]).fx("not")
|
|
41
|
+
return TreeNode(eq.name, [logic3(child) for child in eq.children])
|
|
42
|
+
def logic2(eq):
|
|
43
|
+
if eq.name in ["f_exist", "f_forall"]:
|
|
44
|
+
return TreeNode(eq.name, [eq.children[0], logic2(eq.children[1])])
|
|
45
|
+
if eq.name not in ["f_and", "f_or", "f_not", "f_imply", "f_equiv"]:
|
|
46
|
+
return eq
|
|
47
|
+
def convv(eq):
|
|
48
|
+
if eq == tree_form("s_true"):
|
|
49
|
+
return True
|
|
50
|
+
if eq == tree_form("s_false"):
|
|
51
|
+
return False
|
|
52
|
+
return None
|
|
53
|
+
def conv2(val):
|
|
54
|
+
if val:
|
|
55
|
+
return tree_form("s_true")
|
|
56
|
+
return tree_form("s_false")
|
|
57
|
+
if all(convv(child) is not None for child in eq.children):
|
|
58
|
+
if eq.name == "f_not":
|
|
59
|
+
return conv2(not convv(eq.children[0]))
|
|
60
|
+
elif eq.name == "f_or":
|
|
61
|
+
return conv2(convv(eq.children[0]) or convv(eq.children[1]))
|
|
62
|
+
elif eq.name == "f_and":
|
|
63
|
+
return conv2(convv(eq.children[0]) and convv(eq.children[1]))
|
|
64
|
+
if eq == tree_form("s_false").fx("not"):
|
|
65
|
+
return tree_form("s_true")
|
|
66
|
+
if eq.name == "f_not":
|
|
67
|
+
if eq.children[0].name == "f_not":
|
|
68
|
+
return eq.children[0].children[0]
|
|
69
|
+
elif eq.children[0].name in ["f_or", "f_and"]:
|
|
70
|
+
out = TreeNode({"f_or":"f_and", "f_and":"f_or"}[eq.children[0].name], [])
|
|
71
|
+
for child in eq.children[0].children:
|
|
72
|
+
out.children.append(child.fx("not"))
|
|
73
|
+
return out
|
|
74
|
+
if eq.name in ["f_and", "f_or"]:
|
|
75
|
+
for i in range(len(eq.children)):
|
|
76
|
+
for j in range(len(eq.children)):
|
|
77
|
+
if i ==j:
|
|
78
|
+
continue
|
|
79
|
+
if eq.children[i] == eq.children[j].fx("not"):
|
|
80
|
+
eq2 = copy.deepcopy(eq)
|
|
81
|
+
eq2.children.pop(max(i, j))
|
|
82
|
+
eq2.children.pop(min(i, j))
|
|
83
|
+
eq2.children.append({"f_or":tree_form("s_true"), "f_and":tree_form("s_false")}[eq.name])
|
|
84
|
+
if len(eq2.children) == 1:
|
|
85
|
+
return eq2.children[0]
|
|
86
|
+
return eq2
|
|
87
|
+
if eq.name in ["f_and", "f_or"]:
|
|
88
|
+
for i in range(len(eq.children)):
|
|
89
|
+
if eq.children[i] == tree_form("s_false"):
|
|
90
|
+
eq2 = copy.deepcopy(eq)
|
|
91
|
+
eq2.children.pop(i)
|
|
92
|
+
if eq.name == "f_and":
|
|
93
|
+
return tree_form("s_false")
|
|
94
|
+
if len(eq2.children) == 1:
|
|
95
|
+
return eq2.children[0]
|
|
96
|
+
return eq2
|
|
97
|
+
elif eq.children[i] == tree_form("s_true"):
|
|
98
|
+
eq2 = copy.deepcopy(eq)
|
|
99
|
+
eq2.children.pop(i)
|
|
100
|
+
if eq.name == "f_or":
|
|
101
|
+
return tree_form("s_true")
|
|
102
|
+
if len(eq2.children) == 1:
|
|
103
|
+
return eq2.children[0]
|
|
104
|
+
return eq2
|
|
105
|
+
if eq.name in ["f_and", "f_or"]:
|
|
106
|
+
lst = remove_duplicates_custom(eq.children, lambda x,y: x==y)
|
|
107
|
+
if len(lst) < len(eq.children):
|
|
108
|
+
if len(lst) == 1:
|
|
109
|
+
return lst[0]
|
|
110
|
+
return TreeNode(eq.name, lst)
|
|
111
|
+
|
|
112
|
+
if eq.name in ["f_and", "f_or"] and any(child.children is not None and len(child.children)!=0 for child in eq.children):
|
|
113
|
+
for i in range(len(eq.children),1,-1):
|
|
114
|
+
for item in itertools.combinations(enumerate(eq.children), i):
|
|
115
|
+
op = "f_and"
|
|
116
|
+
if eq.name == "f_and":
|
|
117
|
+
op = "f_or"
|
|
118
|
+
item3 = []
|
|
119
|
+
for item4 in item:
|
|
120
|
+
item3.append(item4[0])
|
|
121
|
+
item5 = []
|
|
122
|
+
for item4 in item:
|
|
123
|
+
item5.append(item4[1])
|
|
124
|
+
item = item5
|
|
125
|
+
out = None
|
|
126
|
+
for j in range(len(item)):
|
|
127
|
+
out = set(item[j].children)
|
|
128
|
+
for item2 in item:
|
|
129
|
+
if item2.name == op:
|
|
130
|
+
out = out & set(item2.children)
|
|
131
|
+
else:
|
|
132
|
+
out = out & set([item2])
|
|
133
|
+
if out == set(item[j].children):
|
|
134
|
+
break
|
|
135
|
+
out = None
|
|
136
|
+
if out is None:
|
|
137
|
+
continue
|
|
138
|
+
out = list(out)
|
|
139
|
+
if out == []:
|
|
140
|
+
continue
|
|
141
|
+
if len(out) != 1:
|
|
142
|
+
out = [TreeNode(op, out)]
|
|
143
|
+
for item4 in list(set(range(len(eq.children))) - set(item3)):
|
|
144
|
+
out.append(eq.children[item4])
|
|
145
|
+
if len(out) == 1:
|
|
146
|
+
return out[0]
|
|
147
|
+
output = flatten_tree(TreeNode(eq.name, out))
|
|
148
|
+
return output
|
|
149
|
+
return TreeNode(eq.name, [flatten_tree(logic2(child)) for child in eq.children])
|
|
150
|
+
def logic1(eq):
|
|
151
|
+
def helper(eq):
|
|
152
|
+
if eq.name in ["f_exist", "f_forall"]:
|
|
153
|
+
return TreeNode(eq.name, [eq.children[0], logic1(eq.children[1])])
|
|
154
|
+
if eq.name not in ["f_and", "f_or", "f_not", "f_imply", "f_equiv"]:
|
|
155
|
+
return eq
|
|
156
|
+
if eq.name == "f_equiv":
|
|
157
|
+
A, B = eq.children
|
|
158
|
+
A, B = logic1(A), logic1(B)
|
|
159
|
+
A, B = dowhile(A, logic2), dowhile(B, logic2)
|
|
160
|
+
return flatten_tree((A & B) | (A.fx("not") & B.fx("not")))
|
|
161
|
+
if eq.name == "f_imply":
|
|
162
|
+
|
|
163
|
+
A, B = eq.children
|
|
164
|
+
A, B = logic1(A), logic1(B)
|
|
165
|
+
A, B = dowhile(A, logic2), dowhile(B, logic2)
|
|
166
|
+
return flatten_tree(A.fx("not") | B)
|
|
167
|
+
return TreeNode(eq.name, [helper(child) for child in eq.children])
|
|
168
|
+
if eq.name in ["f_exist", "f_forall"]:
|
|
169
|
+
return TreeNode(eq.name, [eq.children[0], logic1(eq.children[1])])
|
|
170
|
+
if eq.name not in ["f_and", "f_or", "f_not", "f_imply", "f_equiv"]:
|
|
171
|
+
return eq
|
|
172
|
+
eq = helper(eq)
|
|
173
|
+
eq = flatten_tree(eq)
|
|
174
|
+
|
|
175
|
+
if len(eq.children) > 2:
|
|
176
|
+
lst = []
|
|
177
|
+
l = len(eq.children)
|
|
178
|
+
|
|
179
|
+
# Handle last odd child directly
|
|
180
|
+
if l % 2 == 1:
|
|
181
|
+
last_child = eq.children[-1]
|
|
182
|
+
# expand/simplify only if needed
|
|
183
|
+
if isinstance(last_child, TreeNode):
|
|
184
|
+
last_child = dowhile(last_child, logic2)
|
|
185
|
+
lst.append(last_child)
|
|
186
|
+
l -= 1
|
|
187
|
+
|
|
188
|
+
# Pairwise combine children
|
|
189
|
+
for i in range(0, l, 2):
|
|
190
|
+
left, right = eq.children[i], eq.children[i+1]
|
|
191
|
+
pair = TreeNode(eq.name, [left, right])
|
|
192
|
+
simplified = dowhile(logic1(pair), logic2)
|
|
193
|
+
lst.append(simplified)
|
|
194
|
+
|
|
195
|
+
# If only one element left, just return it instead of nesting
|
|
196
|
+
if len(lst) == 1:
|
|
197
|
+
return flatten_tree(lst[0])
|
|
198
|
+
|
|
199
|
+
# Otherwise rewrap
|
|
200
|
+
return flatten_tree(TreeNode(eq.name, lst))
|
|
201
|
+
|
|
202
|
+
if eq.name == "f_and":
|
|
203
|
+
lst= []
|
|
204
|
+
for child in eq.children:
|
|
205
|
+
if child.name == "f_or":
|
|
206
|
+
lst.append(child.children)
|
|
207
|
+
else:
|
|
208
|
+
lst.append([child])
|
|
209
|
+
out = TreeNode("f_or", [])
|
|
210
|
+
for item in itertools.product(*lst):
|
|
211
|
+
c = TreeNode("f_and", list(item))
|
|
212
|
+
out.children.append(c)
|
|
213
|
+
if len(out.children) == 1:
|
|
214
|
+
out = out.children[0]
|
|
215
|
+
return flatten_tree(out)
|
|
216
|
+
elif eq.name == "f_or":
|
|
217
|
+
lst= []
|
|
218
|
+
for child in eq.children:
|
|
219
|
+
if child.name == "f_and":
|
|
220
|
+
lst.append(child.children)
|
|
221
|
+
else:
|
|
222
|
+
lst.append([child])
|
|
223
|
+
out = TreeNode("f_and", [])
|
|
224
|
+
for item in itertools.product(*lst):
|
|
225
|
+
c = TreeNode("f_or", list(item))
|
|
226
|
+
out.children.append(c)
|
|
227
|
+
if len(out.children) == 1:
|
|
228
|
+
out = out.children[0]
|
|
229
|
+
return flatten_tree(out)
|
|
230
|
+
return TreeNode(eq.name, [logic1(child) for child in eq.children])
|
mathai/matrix.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
def uncommute(eq, inside=False):
|
|
2
|
+
if not inside and eq.name in ["f_add", "f_mul"]:
|
|
3
|
+
return TreeNode(eq.name[:2]+"w"+eq.name[2:], [uncommute(child) for child in eq.children])
|
|
4
|
+
return TreeNode(eq.name, [uncommute(child, True) if eq.name == "f_list" else uncommute(child, inside) for child in eq.children])
|
|
5
|
+
|
|
6
|
+
def matrix_solve(eq):
|
|
7
|
+
if eq.name == "f_wadd":
|
|
8
|
+
output = None
|
|
9
|
+
output2 = []
|
|
10
|
+
for child in eq.children:
|
|
11
|
+
if child.name == "f_list":
|
|
12
|
+
if output is None:
|
|
13
|
+
output = []
|
|
14
|
+
for i in range(len(child.children)):
|
|
15
|
+
output.append([child.children[i]])
|
|
16
|
+
else:
|
|
17
|
+
for i in range(len(child.children)):
|
|
18
|
+
output[i] += [child.children[i]]
|
|
19
|
+
output.append(child)
|
|
20
|
+
else:
|
|
21
|
+
output2.append(child)
|
|
22
|
+
output = [summation(item) for item in output]
|
mathai/ode.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
from .factor import factor
|
|
2
|
+
from .expand import expand
|
|
3
|
+
from .base import *
|
|
4
|
+
from .fraction import fraction
|
|
5
|
+
from .simplify import simplify
|
|
6
|
+
import copy
|
|
7
|
+
|
|
8
|
+
def inversediff(lhs, rhs):
|
|
9
|
+
count = 4
|
|
10
|
+
while contain(rhs, tree_form("v_1")) or contain(lhs, tree_form("v_0")):
|
|
11
|
+
success = False
|
|
12
|
+
if rhs.name == "f_add":
|
|
13
|
+
for i in range(len(rhs.children)-1,-1,-1):
|
|
14
|
+
if not contain(rhs.children[i], tree_form("v_0")) or str_form(tree_form("v_1").fx("dif")) in [str_form(x) for x in factor_generation(rhs.children[i])]:
|
|
15
|
+
if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
|
|
16
|
+
success = True
|
|
17
|
+
lhs = lhs - rhs.children[i]
|
|
18
|
+
rhs.children.pop(i)
|
|
19
|
+
elif rhs.name == "f_mul":
|
|
20
|
+
for i in range(len(rhs.children)-1,-1,-1):
|
|
21
|
+
if not contain(rhs.children[i], tree_form("v_0")):
|
|
22
|
+
if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
|
|
23
|
+
success = True
|
|
24
|
+
lhs = lhs / rhs.children[i]
|
|
25
|
+
rhs.children.pop(i)
|
|
26
|
+
if len(rhs.children) == 1:
|
|
27
|
+
rhs = rhs.children[0]
|
|
28
|
+
rhs, lhs = copy.deepcopy([simplify(lhs), simplify(rhs)])
|
|
29
|
+
if rhs.name == "f_add":
|
|
30
|
+
for i in range(len(rhs.children)-1,-1,-1):
|
|
31
|
+
if not contain(rhs.children[i], tree_form("v_1")) or str_form(tree_form("v_0").fx("dif")) in [str_form(x) for x in factor_generation(rhs.children[i])]:
|
|
32
|
+
if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
|
|
33
|
+
success = True
|
|
34
|
+
lhs = lhs - rhs.children[i]
|
|
35
|
+
rhs.children.pop(i)
|
|
36
|
+
elif rhs.name == "f_mul":
|
|
37
|
+
for i in range(len(rhs.children)-1,-1,-1):
|
|
38
|
+
if not contain(rhs.children[i], tree_form("v_1")):
|
|
39
|
+
if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
|
|
40
|
+
success = True
|
|
41
|
+
lhs = lhs / rhs.children[i]
|
|
42
|
+
rhs.children.pop(i)
|
|
43
|
+
rhs, lhs = copy.deepcopy([simplify(lhs), simplify(rhs)])
|
|
44
|
+
if not success:
|
|
45
|
+
lhs, rhs = factor(lhs),factor(rhs)
|
|
46
|
+
count -= 1
|
|
47
|
+
if count == 0:
|
|
48
|
+
return simplify(e0(lhs-rhs))
|
|
49
|
+
return simplify(e0(lhs-rhs))
|
|
50
|
+
|
|
51
|
+
intconst = ["v_"+str(i) for i in range(101,150)]
|
|
52
|
+
def allocvar():
|
|
53
|
+
global intconst
|
|
54
|
+
return tree_form(intconst.pop(0))
|
|
55
|
+
|
|
56
|
+
def epowersplit(eq):
|
|
57
|
+
if eq.name == "f_pow" and eq.children[1].name == "f_add":
|
|
58
|
+
return product([eq.children[0]**child for child in eq.children[1].children])
|
|
59
|
+
return TreeNode(eq.name, [epowersplit(child) for child in eq.children])
|
|
60
|
+
def esolve(s):
|
|
61
|
+
if s.name == "f_add" and "f_log" in str_form(s):
|
|
62
|
+
return product([tree_form("s_e")**child for child in s.children]) - tree_form("d_1")
|
|
63
|
+
return TreeNode(s.name, [esolve(child) for child in s.children])
|
|
64
|
+
def diffsolve_sep2(eq):
|
|
65
|
+
global tab
|
|
66
|
+
|
|
67
|
+
s = []
|
|
68
|
+
eq = simplify(expand(eq))
|
|
69
|
+
eq = e1(eq)
|
|
70
|
+
|
|
71
|
+
def vlor1(eq):
|
|
72
|
+
if contain(eq, tree_form("v_0")) and not contain(eq, tree_form("v_1")):
|
|
73
|
+
return True
|
|
74
|
+
if contain(eq, tree_form("v_1")) and not contain(eq, tree_form("v_0")):
|
|
75
|
+
return True
|
|
76
|
+
return False
|
|
77
|
+
if eq.name == "f_add" and all(vlor1(child) and [str_form(x) for x in factor_generation(copy.deepcopy(child))].count(str_form(tree_form(vlist(child)[0]).fx("dif")))==1 for child in eq.children):
|
|
78
|
+
for child in eq.children:
|
|
79
|
+
v = vlist(child)[0]
|
|
80
|
+
v2 = tree_form(v).fx("dif")
|
|
81
|
+
child = replace(child, v2, tree_form("d_1"))
|
|
82
|
+
child = simplify(child)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
tmp6 = TreeNode("f_integrate", [child, tree_form(v)])
|
|
86
|
+
s.append(tmp6)
|
|
87
|
+
|
|
88
|
+
if s[-1] is None:
|
|
89
|
+
return None
|
|
90
|
+
s.append(allocvar())
|
|
91
|
+
else:
|
|
92
|
+
return None
|
|
93
|
+
s = summation(s)
|
|
94
|
+
s = simplify(e0(s))
|
|
95
|
+
|
|
96
|
+
return groupe(s)
|
|
97
|
+
def e0(eq):
|
|
98
|
+
return TreeNode("f_eq", [eq, tree_form("d_0")])
|
|
99
|
+
def e1(eq):
|
|
100
|
+
if eq.name == "f_eq":
|
|
101
|
+
eq = eq.children[0]
|
|
102
|
+
return eq
|
|
103
|
+
def groupe(eq):
|
|
104
|
+
eq = esolve(eq)
|
|
105
|
+
eq = simplify(eq)
|
|
106
|
+
eq = fraction(eq)
|
|
107
|
+
eq = simplify(eq)
|
|
108
|
+
eq = epowersplit(eq)
|
|
109
|
+
return eq
|
|
110
|
+
|
|
111
|
+
def diffsolve_sep(eq):
|
|
112
|
+
eq = epowersplit(eq)
|
|
113
|
+
|
|
114
|
+
eq = inversediff(tree_form("d_0"), eq.children[0].copy_tree())
|
|
115
|
+
return eq
|
|
116
|
+
|
|
117
|
+
def diffsolve(eq):
|
|
118
|
+
orig = eq.copy_tree()
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
eq = diffsolve_sep2(eq)
|
|
122
|
+
if eq is None:
|
|
123
|
+
return orig
|
|
124
|
+
return eq
|