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/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