mathai 0.2.1__py3-none-any.whl → 0.2.3__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 +2 -1
- mathai/base.py +2 -1
- mathai/expand.py +2 -0
- mathai/inverse.py +11 -3
- mathai/limit.py +2 -2
- mathai/simplify.py +24 -9
- mathai/univariate_inequality.py +411 -0
- mathai-0.2.3.dist-info/METADATA +231 -0
- {mathai-0.2.1.dist-info → mathai-0.2.3.dist-info}/RECORD +11 -10
- mathai-0.2.1.dist-info/METADATA +0 -24
- {mathai-0.2.1.dist-info → mathai-0.2.3.dist-info}/WHEEL +0 -0
- {mathai-0.2.1.dist-info → mathai-0.2.3.dist-info}/top_level.txt +0 -0
mathai/__init__.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
from .expand import expand
|
2
2
|
from .parser import parse
|
3
3
|
from .printeq import printeq, printeq_log, printeq_str
|
4
|
-
from .simplify import solve, simplify
|
4
|
+
from .simplify import solve, simplify, solve2
|
5
5
|
from .integrate import integrate, sqint, byparts
|
6
6
|
from .diff import diff
|
7
7
|
from .factor import factor, factor2
|
@@ -12,4 +12,5 @@ from .logic import logic0, logic1, logic2, logic3
|
|
12
12
|
from .apart import apart
|
13
13
|
from .console import console
|
14
14
|
from .limit import limit
|
15
|
+
from .univariate_inequality import wavycurvy, absolute, domain, handle_sqrt
|
15
16
|
from .base import *
|
mathai/base.py
CHANGED
mathai/expand.py
CHANGED
mathai/inverse.py
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
from .base import *
|
2
2
|
from .simplify import solve
|
3
3
|
from .expand import expand
|
4
|
-
def inverse(rhs,term):
|
4
|
+
def inverse(rhs,term, sign=None):
|
5
5
|
term = tree_form(term)
|
6
6
|
lhs = tree_form("d_0")
|
7
7
|
count = 15
|
8
|
+
|
8
9
|
while not rhs==term:
|
9
10
|
if rhs.name == "f_add":
|
10
11
|
if all(term in factor_generation(child) for child in rhs.children):
|
@@ -20,6 +21,12 @@ def inverse(rhs,term):
|
|
20
21
|
for i in range(len(rhs.children)-1,-1,-1):
|
21
22
|
if not contain(rhs.children[i], term):
|
22
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
|
+
|
23
30
|
rhs.children.pop(i)
|
24
31
|
elif rhs.name == "f_pow" and contain(rhs.children[0], term):
|
25
32
|
lhs = lhs ** (tree_form("d_1")/rhs.children[1])
|
@@ -53,5 +60,6 @@ def inverse(rhs,term):
|
|
53
60
|
count -= 1
|
54
61
|
if count == 0:
|
55
62
|
return None
|
56
|
-
|
57
|
-
|
63
|
+
if sign is None:
|
64
|
+
return solve(lhs)
|
65
|
+
return solve(lhs), sign
|
mathai/limit.py
CHANGED
@@ -27,13 +27,13 @@ def check(num, den, var):
|
|
27
27
|
if n is None or d is None:
|
28
28
|
return False
|
29
29
|
if n == 0 and d == 0: return True
|
30
|
-
if d != 0: return simplify(
|
30
|
+
if d != 0: return simplify(num/den)
|
31
31
|
return False
|
32
32
|
def lhospital(num, den, steps,var):
|
33
33
|
logs = []
|
34
34
|
out = check(num, den, var)
|
35
35
|
if isinstance(out, TreeNode):
|
36
|
-
return out
|
36
|
+
return out,[]
|
37
37
|
for _ in range(steps):
|
38
38
|
num2, den2 = map(lambda e: simplify(diff(e, var.name)), (num, den))
|
39
39
|
out = check(num2, den2, var)
|
mathai/simplify.py
CHANGED
@@ -144,25 +144,36 @@ def solve(eq, specialfx=False):
|
|
144
144
|
eq = flatten_tree(eq)
|
145
145
|
|
146
146
|
return dowhile(eq, _solve)
|
147
|
-
|
147
|
+
def solve2(eq):
|
148
|
+
return solve(eq, True)
|
148
149
|
def clear_div(eq):
|
149
150
|
lst = factor_generation(eq)
|
150
151
|
if tree_form("d_0") in lst:
|
151
152
|
return tree_form("d_0")
|
152
|
-
|
153
|
+
lst3 = [item for item in lst if "v_" not in str_form(item) and compute(item) < 0]
|
154
|
+
sign = True
|
155
|
+
if len(lst3) % 2 == 1:
|
156
|
+
sign = False
|
157
|
+
lst = [item for item in lst if not(item.name == "f_pow" and frac(item.children[1]) is not None and frac(item.children[1]) == -1)]
|
153
158
|
|
154
159
|
lst2 = [item for item in lst if "v_" in str_form(item)]
|
155
160
|
if lst2 == []:
|
156
|
-
return solve(product(lst))
|
157
|
-
return solve(product(lst2))
|
161
|
+
return solve(product(lst)),sign
|
162
|
+
return solve(product(lst2)),sign
|
158
163
|
|
159
164
|
def simplify(eq):
|
160
165
|
error = False
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
+
eq = flatten_tree(eq)
|
167
|
+
if eq.name in ["f_and", "f_or", "f_not"]:
|
168
|
+
return TreeNode(eq.name, [simplify(child) for child in eq.children])
|
169
|
+
|
170
|
+
if eq.name in ["f_lt", "f_gt", "f_le", "f_ge", "f_eq"]:
|
171
|
+
tmp, sign = clear_div(simplify(eq.children[0]-eq.children[1]))
|
172
|
+
name2 = eq.name
|
173
|
+
if not sign:
|
174
|
+
name2 = {"f_lt":"f_gt", "f_gt":"f_lt", "f_eq":"f_eq", "f_le":"f_ge", "f_ge":"f_le"}[name2]
|
175
|
+
|
176
|
+
return TreeNode(name2, [tmp, tree_form("d_0")])
|
166
177
|
|
167
178
|
eq = solve(eq, True)
|
168
179
|
def helper(eq):
|
@@ -219,6 +230,8 @@ def simplify(eq):
|
|
219
230
|
return TreeNode(eq.name, [helper3(child) for child in eq.children])
|
220
231
|
def helper4(eq):
|
221
232
|
nonlocal error
|
233
|
+
if eq == tree_form("d_-1")**tree_form("d_-1"):
|
234
|
+
return tree_form("d_-1")
|
222
235
|
def perfect_nth_root_value(x, n):
|
223
236
|
"""Return integer y if x is a perfect n-th power (y**n == x), else None."""
|
224
237
|
if x < 0 and n % 2 == 0:
|
@@ -316,6 +329,8 @@ def simplify(eq):
|
|
316
329
|
return eq.children[0].children[0]**eq.children[1]
|
317
330
|
return TreeNode(eq.name, [helper5(child) for child in eq.children])
|
318
331
|
def helper8(eq):
|
332
|
+
if eq.name == "f_pow" and eq.children[0].name == "f_abs" and frac(eq.children[1]) is not None and frac(eq.children[1]).numerator % 2==0:
|
333
|
+
return eq.children[0].children[0] ** eq.children[1]
|
319
334
|
if eq.name == "f_abs" and eq.children[0].name == "f_abs":
|
320
335
|
return eq.children[0]
|
321
336
|
if eq.name == "f_cos" and eq.children[0].name == "f_abs":
|
@@ -0,0 +1,411 @@
|
|
1
|
+
import itertools
|
2
|
+
|
3
|
+
from .base import *
|
4
|
+
from .inverse import inverse
|
5
|
+
from collections import Counter
|
6
|
+
from .factor import factor2
|
7
|
+
from .simplify import simplify, solve
|
8
|
+
from .expand import expand
|
9
|
+
from .fraction import fraction
|
10
|
+
import copy
|
11
|
+
from .diff import diff
|
12
|
+
from .logic import logic0
|
13
|
+
def intersection2(domain, lst):
|
14
|
+
domain = copy.deepcopy(domain)
|
15
|
+
if domain == [True]:
|
16
|
+
return lst
|
17
|
+
elif domain == [True]:
|
18
|
+
return []
|
19
|
+
lst = [item for item in lst if item not in domain]
|
20
|
+
out = []
|
21
|
+
for item2 in lst:
|
22
|
+
for index in range(len(domain)):
|
23
|
+
|
24
|
+
if isinstance(domain[index], bool) and domain[index]:
|
25
|
+
|
26
|
+
if index == 0 and compute(item2) < compute(domain[index+1]):
|
27
|
+
|
28
|
+
out.append(item2)
|
29
|
+
break
|
30
|
+
elif index == len(domain)-1 and compute(domain[index-1]) < compute(item2):
|
31
|
+
out.append(item2)
|
32
|
+
break
|
33
|
+
elif index != 0 and index != len(domain)-1 and compute(domain[index-1]) < compute(item2) and compute(item2) < compute(domain[index+1]):
|
34
|
+
|
35
|
+
out.append(item2)
|
36
|
+
break
|
37
|
+
|
38
|
+
return list(set(out))
|
39
|
+
def flip_less_than(inter):
|
40
|
+
inter = copy.deepcopy(inter)
|
41
|
+
return [not item if isinstance(item, bool) else item for item in inter]
|
42
|
+
def intersection(domain_1, domain_2):
|
43
|
+
domain_1, domain_2 = copy.deepcopy(domain_1), copy.deepcopy(domain_2)
|
44
|
+
if domain_1 == [True]:
|
45
|
+
return domain_2
|
46
|
+
if domain_2 == [True]:
|
47
|
+
return domain_1
|
48
|
+
if domain_1 == [False] or domain_2 == [False]:
|
49
|
+
return [False]
|
50
|
+
def simplify_ranges(ranges):
|
51
|
+
simplified_ranges = []
|
52
|
+
i = 0
|
53
|
+
while i < len(ranges):
|
54
|
+
if i + 2 < len(ranges) and ranges[i] is True and ranges[i + 2] is True:
|
55
|
+
simplified_ranges.append(True)
|
56
|
+
i += 3
|
57
|
+
elif i + 2 < len(ranges) and ranges[i] is False and ranges[i + 2] is False:
|
58
|
+
simplified_ranges.append(False)
|
59
|
+
i += 3
|
60
|
+
else:
|
61
|
+
simplified_ranges.append(ranges[i])
|
62
|
+
i += 1
|
63
|
+
return simplified_ranges
|
64
|
+
result = domain_1 + domain_2
|
65
|
+
result = [item for item in result if not isinstance(item, bool)]
|
66
|
+
result = list(set(result))
|
67
|
+
result = sorted(result, key=lambda x: compute(x))
|
68
|
+
i = len(result)
|
69
|
+
while i>=0:
|
70
|
+
result.insert(i, True)
|
71
|
+
i = i - 1
|
72
|
+
result[0] = domain_1[0] and domain_2[0]
|
73
|
+
result[-1] = domain_1[-1] and domain_2[-1]
|
74
|
+
def find_fraction_in_list(fraction_list, target_fraction):
|
75
|
+
for i in range(1, len(fraction_list)-1, 2):
|
76
|
+
if fraction_list[i] == target_fraction:
|
77
|
+
return i
|
78
|
+
return -1
|
79
|
+
for i in range(2, len(result)-1, 2):
|
80
|
+
if result[i+1] in domain_1:
|
81
|
+
result[i] = result[i] and domain_1[find_fraction_in_list(domain_1, result[i+1])-1]
|
82
|
+
if result[i+1] in domain_2:
|
83
|
+
result[i] = result[i] and domain_2[find_fraction_in_list(domain_2, result[i+1])-1]
|
84
|
+
if result[i-1] in domain_1:
|
85
|
+
result[i] = result[i] and domain_1[find_fraction_in_list(domain_1, result[i-1])+1]
|
86
|
+
if result[i-1] in domain_2:
|
87
|
+
result[i] = result[i] and domain_2[find_fraction_in_list(domain_2, result[i-1])+1]
|
88
|
+
|
89
|
+
result = simplify_ranges(result)
|
90
|
+
return result
|
91
|
+
class Range:
|
92
|
+
def __init__(self, r=[True], p=[], z=[]):
|
93
|
+
self.r = r
|
94
|
+
self.p = p
|
95
|
+
self.z = z
|
96
|
+
self.do = True
|
97
|
+
|
98
|
+
def unfix(self):
|
99
|
+
self.do = False
|
100
|
+
return self
|
101
|
+
def fix(self):
|
102
|
+
if not self.do:
|
103
|
+
return
|
104
|
+
def simplify_ranges(ranges):
|
105
|
+
simplified_ranges = []
|
106
|
+
i = 0
|
107
|
+
while i < len(ranges):
|
108
|
+
if i + 2 < len(ranges) and ranges[i] is True and ranges[i + 2] is True:
|
109
|
+
simplified_ranges.append(True)
|
110
|
+
i += 3
|
111
|
+
elif i + 2 < len(ranges) and ranges[i] is False and ranges[i + 2] is False:
|
112
|
+
simplified_ranges.append(False)
|
113
|
+
i += 3
|
114
|
+
else:
|
115
|
+
simplified_ranges.append(ranges[i])
|
116
|
+
i += 1
|
117
|
+
return simplified_ranges
|
118
|
+
|
119
|
+
self.r = simplify_ranges(self.r)
|
120
|
+
|
121
|
+
common = set(self.p) & set(self.z)
|
122
|
+
self.z = list(set(self.z) - common)
|
123
|
+
self.p = list(set(self.p) - common)
|
124
|
+
|
125
|
+
self.p = list(set(self.p) - set(intersection2(self.r, self.p)))
|
126
|
+
self.z = list(set(intersection2(self.r, self.z)))
|
127
|
+
return self
|
128
|
+
|
129
|
+
def __or__(self, other):
|
130
|
+
return (self.unfix().__invert__().unfix() & other.unfix().__invert__().unfix()).unfix().__invert__().fix()
|
131
|
+
def __invert__(self):
|
132
|
+
tmp = Range(flip_less_than(self.r), self.z, list(set(self.p)-set(self.z)))
|
133
|
+
|
134
|
+
return tmp
|
135
|
+
def __and__(self, other):
|
136
|
+
a = intersection(self.r, other.r)
|
137
|
+
b = intersection2(self.r, other.p)
|
138
|
+
c = intersection2(other.r, self.p)
|
139
|
+
tmp = Range(a, list(set(b)|set(c)|(set(self.p)&set(other.p))), list(set(self.z)|set(other.z)))
|
140
|
+
return tmp
|
141
|
+
def __str__(self):
|
142
|
+
|
143
|
+
if self.r == [False] and self.p == [] and self.z == []:
|
144
|
+
return "{}"
|
145
|
+
out = []
|
146
|
+
out2 = ""
|
147
|
+
if self.r != [False]:
|
148
|
+
for i in range(0, len(self.r), 2):
|
149
|
+
string = ""
|
150
|
+
if self.r[i]:
|
151
|
+
if i == 0:
|
152
|
+
string += "(-inf,"
|
153
|
+
if len(self.r)==1:
|
154
|
+
string += "+inf)"
|
155
|
+
else:
|
156
|
+
string += str(self.r[i+1])+")"
|
157
|
+
elif i == len(self.r)-1 and len(self.r)!=1:
|
158
|
+
string += "("+str(self.r[i-1])+",+inf)"
|
159
|
+
else:
|
160
|
+
string += "("+str(self.r[i-1])+","+str(self.r[i+1])+")"
|
161
|
+
out.append(string)
|
162
|
+
if self.p != []:
|
163
|
+
out.append("{"+",".join([str(item) for item in self.p])+"}")
|
164
|
+
if self.z != []:
|
165
|
+
out2 = "{"+",".join([str(item) for item in self.z])+"}"
|
166
|
+
if out2 == "":
|
167
|
+
return "U".join(out)
|
168
|
+
else:
|
169
|
+
return "U".join(out)+"-"+out2
|
170
|
+
|
171
|
+
dic_table = {}
|
172
|
+
def helper(eq, var="v_0"):
|
173
|
+
global dic_table
|
174
|
+
|
175
|
+
eq2 = copy.deepcopy(eq)
|
176
|
+
|
177
|
+
if eq2 in dic_table.keys():
|
178
|
+
return dic_table[eq2]
|
179
|
+
|
180
|
+
if eq.children[0].name == "f_add":
|
181
|
+
|
182
|
+
eq.children[0] = simplify(expand(eq.children[0]))
|
183
|
+
eq = simplify(factor2(eq))
|
184
|
+
|
185
|
+
|
186
|
+
equ = False
|
187
|
+
sign= True
|
188
|
+
if eq.name in ["f_gt", "f_ge"]:
|
189
|
+
sign = True
|
190
|
+
elif eq.name in ["f_lt", "f_le"]:
|
191
|
+
sign = False
|
192
|
+
if eq.name in ["f_ge", "f_le"]:
|
193
|
+
equ = True
|
194
|
+
if eq.name == "f_eq":
|
195
|
+
equ= True
|
196
|
+
critical = []
|
197
|
+
equal = []
|
198
|
+
more = []
|
199
|
+
|
200
|
+
_, d = num_dem(eq.children[0])
|
201
|
+
d = factor2(d)
|
202
|
+
|
203
|
+
for item in factor_generation(d):
|
204
|
+
|
205
|
+
item = simplify(expand(item))
|
206
|
+
if len(vlist(item)) != 0:
|
207
|
+
v = vlist(item)[0]
|
208
|
+
if diff(diff(item, v), v) != tree_form("d_0"):
|
209
|
+
continue
|
210
|
+
out = inverse(item, vlist(item)[0])
|
211
|
+
more.append(simplify(out))
|
212
|
+
|
213
|
+
eq.children[0] = factor2(eq.children[0])
|
214
|
+
|
215
|
+
|
216
|
+
for item in factor_generation(eq.children[0]):
|
217
|
+
item = simplify(expand(item))
|
218
|
+
|
219
|
+
if len(vlist(item)) == 0:
|
220
|
+
if compute(item) <0:
|
221
|
+
sign = not sign
|
222
|
+
continue
|
223
|
+
v = vlist(item)[0]
|
224
|
+
|
225
|
+
if item.name == "f_pow" and item.children[1].name== "d_-1":
|
226
|
+
|
227
|
+
item = item.children[0]
|
228
|
+
|
229
|
+
tmp2 = diff(copy.deepcopy(item))
|
230
|
+
if "v_" in str_form(tmp2):
|
231
|
+
return None
|
232
|
+
|
233
|
+
|
234
|
+
if diff(diff(item, v), v) != tree_form("d_0"):
|
235
|
+
|
236
|
+
a = replace(diff(diff(item, v), v), tree_form(v), tree_form("d_0"))/tree_form("d_2")
|
237
|
+
if compute(a) < 0:
|
238
|
+
sign = not sign
|
239
|
+
continue
|
240
|
+
|
241
|
+
|
242
|
+
if compute(tmp2)<0:
|
243
|
+
sign = not sign
|
244
|
+
item = simplify(item * tree_form("d_-1"))
|
245
|
+
out = inverse(item, vlist(item)[0])
|
246
|
+
critical.append(out)
|
247
|
+
else:
|
248
|
+
tmp2 = diff(copy.deepcopy(item))
|
249
|
+
if "v_" in str_form(tmp2):
|
250
|
+
return None
|
251
|
+
|
252
|
+
if diff(diff(item, v), v) != tree_form("d_0"):
|
253
|
+
a = replace(diff(diff(item, v), v), tree_form(v), tree_form("d_0"))/tree_form("d_2")
|
254
|
+
if compute(a) < 0:
|
255
|
+
sign = not sign
|
256
|
+
continue
|
257
|
+
|
258
|
+
|
259
|
+
if compute(tmp2)<0:
|
260
|
+
sign = not sign
|
261
|
+
item = simplify(item * tree_form("d_-1"))
|
262
|
+
out = inverse(item, vlist(item)[0])
|
263
|
+
critical.append(out)
|
264
|
+
if equ:
|
265
|
+
equal.append(str_form(out))
|
266
|
+
equal = list(set([simplify(tree_form(item)) for item in equal]))
|
267
|
+
more = list(set([simplify(tree_form(item)) for item in more]))
|
268
|
+
critical = [simplify(item) for item in critical]
|
269
|
+
critical = Counter(critical)
|
270
|
+
|
271
|
+
critical = sorted(critical.items(), key=lambda x: compute(x[0]))
|
272
|
+
|
273
|
+
i = len(critical)
|
274
|
+
element = sign
|
275
|
+
while i>=0:
|
276
|
+
critical.insert(i, element)
|
277
|
+
if i>0 and critical[i-1][1] % 2 != 0:
|
278
|
+
element = not element
|
279
|
+
i = i - 1
|
280
|
+
for i in range(1, len(critical), 2):
|
281
|
+
critical[i] = critical[i][0]
|
282
|
+
|
283
|
+
|
284
|
+
|
285
|
+
if eq.name == "f_eq":
|
286
|
+
final = Range([False], equal, more)
|
287
|
+
dic_table[eq2] = final
|
288
|
+
return final
|
289
|
+
|
290
|
+
final = Range(critical, equal, more)
|
291
|
+
dic_table[eq2] = final
|
292
|
+
return final
|
293
|
+
def wavycurvy(eq):
|
294
|
+
if eq.name == "s_true":
|
295
|
+
return Range([True])
|
296
|
+
if eq.name == "s_false":
|
297
|
+
return Range([False])
|
298
|
+
if eq.name not in ["f_and", "f_or", "f_not"]:
|
299
|
+
|
300
|
+
out = helper(eq)
|
301
|
+
if out is None:
|
302
|
+
return None
|
303
|
+
return out
|
304
|
+
lst= [wavycurvy(child) for child in eq.children]
|
305
|
+
if None in lst:
|
306
|
+
return None
|
307
|
+
ra = lst[0]
|
308
|
+
if eq.name == "f_and":
|
309
|
+
for child in lst[1:]:
|
310
|
+
ra = ra & child
|
311
|
+
elif eq.name == "f_or":
|
312
|
+
for child in lst[1:]:
|
313
|
+
ra = ra | child
|
314
|
+
elif eq.name == "f_not":
|
315
|
+
ra = ~ra
|
316
|
+
return ra
|
317
|
+
|
318
|
+
def absolute(equation):
|
319
|
+
if equation.name in ["f_and", "f_or", "f_not"]:
|
320
|
+
tmp = TreeNode(equation.name, [absolute(child) for child in equation.children])
|
321
|
+
if len(tmp.children)==1:
|
322
|
+
tmp =tmp.children[0]
|
323
|
+
return tmp
|
324
|
+
def mul_abs(eq):
|
325
|
+
if eq.name == "f_abs" and eq.children[0].name == "f_mul":
|
326
|
+
return simplify(product([item.fx("abs") for item in factor_generation(eq.children[0])]))
|
327
|
+
return TreeNode(eq.name, [mul_abs(child) for child in eq.children])
|
328
|
+
equation = mul_abs(equation)
|
329
|
+
|
330
|
+
def collectabs(eq):
|
331
|
+
out = []
|
332
|
+
if eq.name == "f_abs":
|
333
|
+
out.append(eq.children[0])
|
334
|
+
return out
|
335
|
+
for child in eq.children:
|
336
|
+
out += collectabs(child)
|
337
|
+
return out
|
338
|
+
def abc(eq, arr):
|
339
|
+
def trans(eq):
|
340
|
+
nonlocal arr
|
341
|
+
out = {}
|
342
|
+
if eq.name == "f_abs":
|
343
|
+
x = arr.pop(0)
|
344
|
+
if x == 0 or x==2:
|
345
|
+
return eq.children[0]
|
346
|
+
else:
|
347
|
+
return -eq.children[0]
|
348
|
+
else:
|
349
|
+
return TreeNode(eq.name, [trans(child) for child in eq.children])
|
350
|
+
return trans(eq)
|
351
|
+
out = list(set(collectabs(equation)))
|
352
|
+
|
353
|
+
out2 = []
|
354
|
+
for item in itertools.product([0,1,2], repeat=len(out)):
|
355
|
+
out3 = []
|
356
|
+
for i in range(len(item)):
|
357
|
+
out3.append(copy.deepcopy(TreeNode({0:"f_gt", 1:"f_lt", 2:"f_eq"}[item[i]], [out[i], tree_form("d_0")])))
|
358
|
+
out3 = TreeNode("f_and", out3+[abc(copy.deepcopy(equation), list(item))])
|
359
|
+
if len(out3.children) == 1:
|
360
|
+
out3 = out3.children[0]
|
361
|
+
out2.append(out3)
|
362
|
+
if len(out2) == 1:
|
363
|
+
return out2[0]
|
364
|
+
else:
|
365
|
+
equation = TreeNode("f_or", out2)
|
366
|
+
return equation
|
367
|
+
def handle_sqrt(eq):
|
368
|
+
eq = domain(eq)
|
369
|
+
def helper2(eq):
|
370
|
+
if eq.name in ["f_lt", "f_gt", "f_le", "f_ge"]:
|
371
|
+
out = []
|
372
|
+
def helper(eq):
|
373
|
+
nonlocal out
|
374
|
+
if eq.name == "f_pow" and frac(eq.children[1]) == Fraction(1,2):
|
375
|
+
out.append(simplify(eq))
|
376
|
+
x = [helper(child) for child in eq.children]
|
377
|
+
helper(eq)
|
378
|
+
for item in out:
|
379
|
+
|
380
|
+
eq2, sgn = inverse(simplify(eq.children[0]), str_form(item), True)
|
381
|
+
n = tree_form("d_1")
|
382
|
+
if sgn == False:
|
383
|
+
n = tree_form("d_-1")
|
384
|
+
eq3 = simplify(expand(simplify(eq2**2)))
|
385
|
+
eq2 = simplify(eq2)
|
386
|
+
if "v_" in str_form(eq3) and not (eq2.name == "f_pow" and frac(eq2.children[1]) == Fraction(1,2)):
|
387
|
+
return simplify(TreeNode(eq.name, [simplify(n*item.children[0]-eq3*n), tree_form("d_0")])) & TreeNode("f_ge", [eq2, tree_form("d_0")])
|
388
|
+
return simplify(TreeNode(eq.name, [simplify(n*item.children[0]-eq3*n), tree_form("d_0")]))
|
389
|
+
return TreeNode(eq.name, [helper2(child) for child in eq.children])
|
390
|
+
return helper2(eq)
|
391
|
+
def domain(eq):
|
392
|
+
eq = solve(eq, True)
|
393
|
+
out = []
|
394
|
+
def helper2(eq):
|
395
|
+
nonlocal out
|
396
|
+
if eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]).denominator == 2:
|
397
|
+
out.append(TreeNode("f_ge", [eq.children[0], tree_form("d_0")]))
|
398
|
+
if eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]) <0:
|
399
|
+
out.append(TreeNode("f_eq", [eq.children[0], tree_form("d_0")]).fx("not"))
|
400
|
+
x = [helper2(child) for child in eq.children]
|
401
|
+
helper2(eq)
|
402
|
+
out = list(set([simplify(item) for item in out]))
|
403
|
+
if out == []:
|
404
|
+
return eq
|
405
|
+
if len(out)==1:
|
406
|
+
out = out[0]
|
407
|
+
else:
|
408
|
+
out = TreeNode("f_and", list(out))
|
409
|
+
if eq.name in ["f_lt", "f_gt", "f_le", "f_ge", "f_eq"]:
|
410
|
+
return eq & out
|
411
|
+
return out
|
@@ -0,0 +1,231 @@
|
|
1
|
+
Metadata-Version: 2.2
|
2
|
+
Name: mathai
|
3
|
+
Version: 0.2.3
|
4
|
+
Summary: Mathematics solving Ai tailored to NCERT
|
5
|
+
Home-page: https://github.com/infinity390/mathai4
|
6
|
+
Author: educated indians are having a low iq and are good for nothing
|
7
|
+
Requires-Python: >=3.7
|
8
|
+
Description-Content-Type: text/markdown
|
9
|
+
Requires-Dist: lark-parser
|
10
|
+
Dynamic: author
|
11
|
+
Dynamic: description
|
12
|
+
Dynamic: description-content-type
|
13
|
+
Dynamic: home-page
|
14
|
+
Dynamic: requires-dist
|
15
|
+
Dynamic: requires-python
|
16
|
+
Dynamic: summary
|
17
|
+
|
18
|
+
# Math AI Documentation
|
19
|
+
|
20
|
+
## Philosophy
|
21
|
+
I think it is a big realization in computer science and programming to realize that computers can solve mathematics.
|
22
|
+
This understanding should be made mainstream. It can help transform education, mathematical research, and computation of mathematical equations for work.
|
23
|
+
|
24
|
+
## Societal Implications Of Such A Computer Program And The Author's Comment On Universities Of India
|
25
|
+
I think mathematics is valued by society because of education. Schools and universities teach them.
|
26
|
+
So this kind of software, if made mainstream, could bring real change.
|
27
|
+
|
28
|
+
### The Author's Comments On The Universities In His Country
|
29
|
+
> Educated Indians are having a low IQ and are good for nothing.
|
30
|
+
> The Indian Institute of Technology (IITs) graduates are the leader of the fools.
|
31
|
+
> Every educated Indian is beneath me.
|
32
|
+
> Now learn how this Python library can solve the math questions of your exams.
|
33
|
+
|
34
|
+
## The Summary Of How Computer "Solves" Math
|
35
|
+
Math equations are a tree data structure (`TreeNode` class).
|
36
|
+
We can manipulate the math equations using various algorithms (functions provided by the `mathai` library).
|
37
|
+
We first parse the math equation strings to get the tree data structure (`parse` function in `mathai`).
|
38
|
+
|
39
|
+
## The Library
|
40
|
+
Import the library by doing:
|
41
|
+
|
42
|
+
```python
|
43
|
+
from mathai import *
|
44
|
+
```
|
45
|
+
|
46
|
+
### str_form
|
47
|
+
It is the string representation of a `TreeNode` math equation.
|
48
|
+
|
49
|
+
#### Example
|
50
|
+
```text
|
51
|
+
(cos(x)^2)+(sin(x)^2)
|
52
|
+
```
|
53
|
+
|
54
|
+
Is represented internally as:
|
55
|
+
|
56
|
+
```text
|
57
|
+
f_add
|
58
|
+
f_pow
|
59
|
+
f_cos
|
60
|
+
v_0
|
61
|
+
d_2
|
62
|
+
f_pow
|
63
|
+
f_sin
|
64
|
+
v_0
|
65
|
+
d_2
|
66
|
+
```
|
67
|
+
|
68
|
+
#### Leaf Nodes
|
69
|
+
|
70
|
+
**Variables** (start with a `v_` prefix):
|
71
|
+
|
72
|
+
- `v_0` → x
|
73
|
+
- `v_1` → y
|
74
|
+
- `v_2` → z
|
75
|
+
- `v_3` → a
|
76
|
+
|
77
|
+
**Numbers** (start with `d_` prefix; only integers):
|
78
|
+
|
79
|
+
- `d_-1` → -1
|
80
|
+
- `d_0` → 0
|
81
|
+
- `d_1` → 1
|
82
|
+
- `d_2` → 2
|
83
|
+
|
84
|
+
#### Branch Nodes
|
85
|
+
- `f_add` → addition
|
86
|
+
- `f_mul` → multiplication
|
87
|
+
- `f_pow` → power
|
88
|
+
|
89
|
+
### parse
|
90
|
+
Takes a math equation string and outputs a `TreeNode` object.
|
91
|
+
|
92
|
+
```python
|
93
|
+
from mathai import *
|
94
|
+
|
95
|
+
equation = parse("sin(x)^2+cos(x)^2")
|
96
|
+
print(equation)
|
97
|
+
```
|
98
|
+
|
99
|
+
#### Output
|
100
|
+
```text
|
101
|
+
(cos(x)^2)+(sin(x)^2)
|
102
|
+
```
|
103
|
+
|
104
|
+
### printeq, printeq_str, printeq_log
|
105
|
+
Prints math equations in a more readable form than usual `print`.
|
106
|
+
|
107
|
+
```python
|
108
|
+
from mathai import *
|
109
|
+
|
110
|
+
equation = simplify(parse("(x+1)/x"))
|
111
|
+
print(equation)
|
112
|
+
printeq(equation)
|
113
|
+
```
|
114
|
+
|
115
|
+
#### Output
|
116
|
+
```text
|
117
|
+
(1+x)*(x^-1)
|
118
|
+
(1+x)/x
|
119
|
+
```
|
120
|
+
|
121
|
+
### solve, simplify
|
122
|
+
`simplify` performs what `solve` does and more.
|
123
|
+
It simplifies and cleans up a given math equation.
|
124
|
+
|
125
|
+
```python
|
126
|
+
from mathai import *
|
127
|
+
|
128
|
+
equation = simplify(parse("(x+x+x+x-1-1-1-1)*(4*x-4)*sin(sin(x+x+x)*sin(3*x))"))
|
129
|
+
printeq(equation)
|
130
|
+
```
|
131
|
+
|
132
|
+
#### Output
|
133
|
+
```text
|
134
|
+
((-4+(4*x))^2)*sin((sin((3*x))^2))
|
135
|
+
```
|
136
|
+
|
137
|
+
### Incomplete Documentation, Will be updated and completed later on
|
138
|
+
|
139
|
+
### Example Demonstration [limits questions can also be solved other than this these, try limit()]
|
140
|
+

|
141
|
+
```python
|
142
|
+
import sys, os, time
|
143
|
+
from mathai import *
|
144
|
+
|
145
|
+
sys.setrecursionlimit(10000)
|
146
|
+
|
147
|
+
def integration_byparts(item): return simplify(fraction(simplify(byparts(simplify(parse(item)))[0])))
|
148
|
+
def integration_apart(item): return simplify(fraction(integrate(apart(factor2(simplify(parse(item)))))[0]))
|
149
|
+
def integration_direct(item): return simplify(fraction(simplify(integrate(simplify(parse(item)))[0])))
|
150
|
+
def integration_trig(item): return simplify(trig0(integrate(trig1(simplify(parse(item))))[0]))
|
151
|
+
def algebra(item): return logic0(simplify(expand(simplify(parse(item)))))
|
152
|
+
def trig_basic(item): return logic0(simplify(expand(trig3(simplify(parse(item))))))
|
153
|
+
def trig_advanced(item): return logic0(simplify(trig0(trig1(trig4(simplify(fraction(trig0(simplify(parse(item))))))))))
|
154
|
+
|
155
|
+
all_tasks = [
|
156
|
+
*[(item, trig_advanced) for item in [
|
157
|
+
"cos(x)/(1+sin(x)) + (1+sin(x))/cos(x) = 2*sec(x)",
|
158
|
+
"(1+sec(x))/sec(x) = sin(x)^2/(1-cos(x))"]],
|
159
|
+
*[(item, integration_byparts) for item in ["sin(x)*x","x*sin(3*x)","x*log(abs(x))","arctan(x)"]],
|
160
|
+
*[(item, integration_apart) for item in ["x/((x+1)*(x+2))","1/(x^2-9)"]],
|
161
|
+
*[(item, integration_direct) for item in [
|
162
|
+
"x*sqrt(x+2)","sin(cos(x))*sin(x)","2*x/(1+x^2)","sqrt(a*x+b)","cos(sqrt(x))/sqrt(x)","e^(arctan(x))/(1+x^2)","sqrt(sin(2*x))*cos(2*x"]],
|
163
|
+
*[(item, integration_trig) for item in ["sin(2*x+5)^2","sin(x)^4","cos(2*x)^4"]],
|
164
|
+
*[(item, algebra) for item in ["(x+1)^2 = x^2+2*x+1","(x+1)*(x-1) = x^2-1"]],
|
165
|
+
*[(item, trig_basic) for item in ["2*sin(x)*cos(x)=sin(2*x)"]],
|
166
|
+
]
|
167
|
+
|
168
|
+
def run_task(task):
|
169
|
+
item, func = task
|
170
|
+
try: result = func(item)
|
171
|
+
except Exception as e: result = str(e)
|
172
|
+
return item, result
|
173
|
+
|
174
|
+
if __name__=="__main__":
|
175
|
+
print(f"Solving {len(all_tasks)} math questions...\n")
|
176
|
+
start_time = time.time()
|
177
|
+
for task in all_tasks:
|
178
|
+
item, result = run_task(task)
|
179
|
+
print(f"{item} => {result}\n")
|
180
|
+
print(f"All tasks completed in {time.time()-start_time:.2f} seconds")
|
181
|
+
```
|
182
|
+
### Output
|
183
|
+
|
184
|
+
```
|
185
|
+
Running 21 tasks asynchronously on 8 cores...
|
186
|
+
|
187
|
+
x*log(abs(x)) => ((-2*(x^2))+(4*log(abs(x))*(x^2)))*(8^-1)
|
188
|
+
|
189
|
+
arctan(x) => (log((abs((1+(x^2)))^-1))+(2*arctan(x)*x))*(2^-1)
|
190
|
+
|
191
|
+
sin(cos(x))*sin(x) => cos(cos(x))
|
192
|
+
|
193
|
+
1/(x^2-9) => (log(abs((-3+x)))+log((abs((3+x))^-1)))*(6^-1)
|
194
|
+
|
195
|
+
x/((x+1)*(x+2)) => log((abs((1+x))^-1))+log(((2+x)^2))
|
196
|
+
|
197
|
+
x*sin(3*x) => ((-9*cos((3*x))*x)+(3*sin((3*x))))*(27^-1)
|
198
|
+
|
199
|
+
(1+sec(x))/sec(x) = sin(x)^2/(1-cos(x)) => true
|
200
|
+
|
201
|
+
e^(arctan(x))/(1+x^2) => e^arctan(x)
|
202
|
+
|
203
|
+
cos(sqrt(x))/sqrt(x) => 2*sin((x^(2^-1)))
|
204
|
+
|
205
|
+
sqrt(a*x+b) => 2*(3^-1)*(((x*a)+b)^(3*(2^-1)))*(a^-1)
|
206
|
+
|
207
|
+
sin(x)*x => (-1*cos(x)*x)+sin(x)
|
208
|
+
|
209
|
+
(x+1)^2 = x^2+2*x+1 => true
|
210
|
+
|
211
|
+
(x+1)*(x-1) = x^2-1 => true
|
212
|
+
|
213
|
+
cos(x)/(1+sin(x)) + (1+sin(x))/cos(x) = 2*sec(x) => true
|
214
|
+
|
215
|
+
2*sin(x)*cos(x)=sin(2*x) => true
|
216
|
+
|
217
|
+
sqrt(sin(2*x))*cos(2*x) => (3^-1)*(sin((2*x))^(3*(2^-1)))
|
218
|
+
|
219
|
+
2*x/(1+x^2) => log(abs((1+(x^2))))
|
220
|
+
|
221
|
+
sin(2*x+5)^2 => ((-1*(4^-1)*sin((10+(4*x))))+x)*(2^-1)
|
222
|
+
|
223
|
+
cos(2*x)^4 => ((4^-1)*x)+((64^-1)*sin((8*x)))+((8^-1)*sin((4*x)))+((8^-1)*x)
|
224
|
+
|
225
|
+
x*sqrt(x+2) => ((-1*(4^-1)*((2+x)^(2+(2^-1))))+(-2*((2+x)^(2+(2^-1))))+(5*((2+x)^(1+(2^-1)))*x)+((2^-1)*((2+x)^(1+(2^-1)))*x)+((8^-1)*((2+x)^(1+(2^-1)))*x))*((1+(2^-1))^-3)*((2+(2^-1))^-1)
|
226
|
+
|
227
|
+
sin(x)^4 => (-1*(4^-1)*sin((2*x)))+((32^-1)*sin((4*x)))+((4^-1)*x)+((8^-1)*x)
|
228
|
+
|
229
|
+
All tasks completed in 129.78 seconds
|
230
|
+
```
|
231
|
+
|
@@ -1,23 +1,24 @@
|
|
1
|
-
mathai/__init__.py,sha256=
|
1
|
+
mathai/__init__.py,sha256=1e8IUnfQv45U_EIp4GS_ugwVQlqQPWoWn3td5pTF5Lk,615
|
2
2
|
mathai/apart.py,sha256=P0B21wHUFitc5RGbNJlwSeOdseOMcav4I7teFNcZmFA,3130
|
3
|
-
mathai/base.py,sha256=
|
3
|
+
mathai/base.py,sha256=8grzVyhvSrlpBRe-0ThkVGJtl9uokwzeOVHT1GcgznQ,12330
|
4
4
|
mathai/console.py,sha256=FsEMqDsgFeBSUiPCm9sfReZp56NSyoFVldqmVwvW4lg,3119
|
5
5
|
mathai/diff.py,sha256=Dvc-tuiW8jLncybjGqHs2WTg2vpMEdRJqUoIdnDj4sk,2879
|
6
|
-
mathai/expand.py,sha256=
|
6
|
+
mathai/expand.py,sha256=IqkxHS8lqbk0PZqz2y_IbRMSP0GExV6fneYwVEWQ9XM,1831
|
7
7
|
mathai/factor.py,sha256=1-Bxl3MX6P1mYM-CX0hRskCrTZWHFdaUL-V1OqX48hY,5316
|
8
8
|
mathai/fraction.py,sha256=KGldpi8mndp5cvp6qbN7ZdMZyVmK6popa3AwkWmHXl4,2573
|
9
9
|
mathai/integrate.py,sha256=I_9hIi3m9eoYjYwBbp_Bu1VXVRiXbUqYcJfL3cpLBPk,12652
|
10
|
-
mathai/inverse.py,sha256=
|
11
|
-
mathai/limit.py,sha256=
|
10
|
+
mathai/inverse.py,sha256=QCvDrzKquWsZv-BDAzZd9HnU0c3gZvcc44UztHVO5LQ,2919
|
11
|
+
mathai/limit.py,sha256=hmh7hgZHMHqkfLui5KSNtGfkUBzNTBvVmDkFNiXupXo,4862
|
12
12
|
mathai/linear.py,sha256=eVnDbJYC1TWwg4J7ovBKsaHYlSoDmXk5jQpsqwtVPyI,5481
|
13
13
|
mathai/logic.py,sha256=UvHzRmKcO9AD51tRzHmpNSEhgW5gmaf4XPaQKFjGfC4,9653
|
14
14
|
mathai/parser.py,sha256=ENtMMm7Q_5QZL6cjbwsXGVJv-H53ueCPGEosJy4LcjY,6809
|
15
15
|
mathai/printeq.py,sha256=JTB0_RBcgt1yFviqlHtXGXuSXcpKrxzSxj5WHkOHon4,1318
|
16
|
-
mathai/simplify.py,sha256=
|
16
|
+
mathai/simplify.py,sha256=Fs4Ggu4pSpZw5GrEFmXs8YMLWJ8NeYhJZSdnwG1H5U4,14939
|
17
17
|
mathai/structure.py,sha256=Hgw2y43dwasa6G8z6OS2lmReh7JHwlChGn-FUdEaWY8,4106
|
18
18
|
mathai/tool.py,sha256=87N5Ya7DmHdFOobTYDAjPHNWZuMzMIDjYN0ZtlHjxqE,1099
|
19
19
|
mathai/trig.py,sha256=ywu89MJfAB81JCzsVPBLpGGv8od0LhLn5cgDtLtYwmw,6897
|
20
|
-
mathai
|
21
|
-
mathai-0.2.
|
22
|
-
mathai-0.2.
|
23
|
-
mathai-0.2.
|
20
|
+
mathai/univariate_inequality.py,sha256=osifXsXDAbyv6Rr6AaiBONBPu4kzaaNxTjuMKTphUEQ,14739
|
21
|
+
mathai-0.2.3.dist-info/METADATA,sha256=6jMZWRA0amOclCUg4xA0HGDNlpijkN_G6JkDDT3FEno,7087
|
22
|
+
mathai-0.2.3.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
23
|
+
mathai-0.2.3.dist-info/top_level.txt,sha256=ROP4l3OhGYw3ihkQGASr18xM9GsK4z3_6whV5AyXLwE,7
|
24
|
+
mathai-0.2.3.dist-info/RECORD,,
|
mathai-0.2.1.dist-info/METADATA
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.2
|
2
|
-
Name: mathai
|
3
|
-
Version: 0.2.1
|
4
|
-
Summary: Mathematics solving Ai tailored to NCERT
|
5
|
-
Home-page: https://github.com/infinity390/mathai4
|
6
|
-
Author: educated indians are having a low iq and are good for nothing
|
7
|
-
Requires-Python: >=3.7
|
8
|
-
Description-Content-Type: text/markdown
|
9
|
-
Requires-Dist: lark-parser
|
10
|
-
Dynamic: author
|
11
|
-
Dynamic: description
|
12
|
-
Dynamic: description-content-type
|
13
|
-
Dynamic: home-page
|
14
|
-
Dynamic: requires-dist
|
15
|
-
Dynamic: requires-python
|
16
|
-
Dynamic: summary
|
17
|
-
|
18
|
-
educated indians are having a low iq and are good for nothing
|
19
|
-
|
20
|
-
the indian institute of technology graduates are the leader of the fools
|
21
|
-
|
22
|
-
every educated indian is beneath me
|
23
|
-
|
24
|
-
now learn how this python library can solve the math questions of your exams
|
File without changes
|
File without changes
|