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 ADDED
@@ -0,0 +1,53 @@
1
+ from .ode import diffsolve as ode_solve
2
+ from .ode import diffsolve_sep as ode_shift_term
3
+
4
+ from .linear import linear_solve, linear_or
5
+
6
+ from .expand import expand
7
+
8
+ from .parser import parse
9
+
10
+ from .printeq import printeq, printeq_log, printeq_str
11
+
12
+ from .simplify import simplify
13
+
14
+ from .integrate import ref as integrate_save
15
+ from .integrate import integrate_subs_main as integrate_subs
16
+ from .integrate import byparts as integrate_byparts
17
+ from .integrate import sqint as integrate_fraction
18
+ from .integrate import integrate_summation
19
+ from .integrate import rm_const as integrate_const
20
+ from .integrate import solve_integrate as integrate_clean
21
+ from .integrate import inteq as integrate_recursive
22
+ from .integrate import integrate_formula
23
+
24
+ from .diff import diff
25
+
26
+ from .factor import factor as factor1
27
+ from .factor import factor2, factor3
28
+ from .factor import rationalize_sqrt as rationalize
29
+ from .factor import merge_sqrt
30
+ from .factor import factorconst as factor0
31
+
32
+ from .fraction import fraction
33
+
34
+ from .inverse import inverse
35
+
36
+ from .trig import trig0, trig1, trig2, trig3, trig4
37
+
38
+ from .logic import logic0, logic1, logic2, logic3, logic_n
39
+
40
+ from .apart import apart, apart2
41
+
42
+ from .limit import limit1, limit2, limit0, limit3
43
+
44
+ from .univariate_inequality import wavycurvy, absolute, domain, handle_sqrt, prepare
45
+ from .bivariate_inequality import inequality_solve
46
+
47
+ from .matrix import uncommute
48
+
49
+ from .base import *
50
+
51
+ from .tool import enclose_const
52
+ from .tool import poly_simplify
53
+ from .tool import longdiv
mathai/apart.py ADDED
@@ -0,0 +1,142 @@
1
+ from .linear import linear_solve
2
+ from .expand import expand
3
+ from .simplify import simplify
4
+
5
+ from .diff import diff
6
+ from .inverse import inverse
7
+ from .base import *
8
+ import math
9
+ from .factor import factor2
10
+ from .tool import poly, enclose_const, longdiv
11
+
12
+ def _apart(eq, v=None):
13
+
14
+ if v is None:
15
+ if len(vlist(eq)) == 0:
16
+ return eq
17
+ v = vlist(eq)[0]
18
+ origv = vlist(eq)
19
+
20
+ if eq.name != "f_mul":
21
+ return eq
22
+
23
+ if any("f_"+item in str_form(eq) for item in "sin cos tan log".split(" ")):
24
+ return eq
25
+
26
+ def exclude(eq):
27
+ if eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]).denominator != 1:
28
+ return False
29
+ if any(not exclude(child) for child in eq.children):
30
+ return False
31
+ return True
32
+
33
+ if not exclude(eq):
34
+ return eq
35
+
36
+ def countfac(lst, eq):
37
+ count=0
38
+ for item in lst:
39
+ if simplify(expand(simplify(eq - item))) == tree_form("d_0"):
40
+ count += 1
41
+ return tree_form("d_"+str(count))
42
+
43
+ alloclst = []
44
+ for i in range(0,26):
45
+ if "v_"+str(i) not in vlist(eq):
46
+ alloclst.append(tree_form("v_"+str(i)))
47
+
48
+ nn, d = num_dem(eq)
49
+
50
+ s = []
51
+ facd = [simplify(x) for x in factor_generation(simplify(d))]
52
+
53
+
54
+ facd2 = remove_duplicates_custom(facd, lambda m, n: simplify(expand(simplify(m-n))) == tree_form("d_0"))
55
+
56
+ if len(facd2) == 1:
57
+ return eq
58
+ x = tree_form(v)
59
+ num = []
60
+ dem = []
61
+
62
+ for item in facd2:
63
+
64
+ g = countfac(facd, item)
65
+ for n in range(int(g.name[2:])):
66
+ n = n+1
67
+ if n > 3:
68
+ return eq
69
+ n = tree_form("d_"+str(n))
70
+
71
+ l = len(poly(item, v))
72
+ if l == 3:
73
+ a = alloclst.pop(0)
74
+ b = alloclst.pop(0)
75
+ if n == tree_form("d_1"):
76
+ num.append(a*x+ b)
77
+ dem.append(item)
78
+ s.append((a*x+ b)/item)
79
+ else:
80
+ num.append(a*x+ b)
81
+ dem.append(item**n)
82
+ s.append((a*x+ b)/item**n)
83
+ elif l == 2:
84
+ a = alloclst.pop(0)
85
+ if n == tree_form("d_1"):
86
+ num.append(a)
87
+ dem.append(item)
88
+ s.append(a/item)
89
+ else:
90
+ num.append(a)
91
+ dem.append(item**n)
92
+ s.append(a/item**n)
93
+ else:
94
+
95
+ return eq
96
+ final3 = summation(s)
97
+
98
+ eq2 = simplify(nn*product(dem)/d)
99
+
100
+ final2 = []
101
+ for i in range(len(num)):
102
+ final2.append(product([dem[k] for k in range(len(dem)) if i != k])*num[i])
103
+
104
+ final = summation(final2)
105
+
106
+ s = simplify(TreeNode("f_eq", [final-eq2, tree_form("d_0")]))
107
+
108
+ lst = poly(s.children[0], v)
109
+
110
+ lst = [TreeNode("f_eq", [item, tree_form("d_0")]) for item in lst if "v_" in str_form(item)]
111
+ lst2 = []
112
+ for item in lst:
113
+ lst2+=vlist(item)
114
+ origv = list(set(lst2)-set(origv))
115
+
116
+ out = linear_solve(TreeNode("f_and", lst), [tree_form(item) for item in origv])
117
+ for item in out.children:
118
+
119
+ final3 = replace(final3, tree_form(list(set(vlist(item))&set(origv))[0]), inverse(item.children[0], list(set(vlist(item))&set(origv))[0]))
120
+ final4 = simplify(final3)
121
+
122
+ return final4
123
+ def apart2(eq):
124
+ if eq.name == "f_mul":
125
+
126
+ a, b = num_dem(eq)
127
+
128
+ tmp = longdiv(a, b, 2, 1)
129
+
130
+ if tmp is not None:
131
+ return simplify(tmp[0]+tmp[1]/b)
132
+ return TreeNode(eq.name, [apart2(child) for child in eq.children])
133
+ def apart(eq):
134
+ eq = factor2(simplify(eq))
135
+ eq, fx = enclose_const(eq)
136
+ def helper(eq):
137
+ eq2 = _apart(eq)
138
+ if eq != eq2:
139
+ return eq2
140
+
141
+ return TreeNode(eq.name, [helper(child) for child in eq.children])
142
+ return fx(helper(eq))
mathai/base.py ADDED
@@ -0,0 +1,419 @@
1
+ import copy
2
+ from fractions import Fraction
3
+
4
+ class TreeNode:
5
+ def __init__(self, name, children=[]):
6
+
7
+ children = [child.copy_tree() for child in children]
8
+ self.name = name
9
+ if name in ["f_add", "f_mul"]:
10
+ self.children = sorted(children, key=lambda x: str_form(x))
11
+ else:
12
+ self.children = children
13
+
14
+ def fx(self, fxname):
15
+ return TreeNode("f_" + fxname, [self])
16
+ def copy_tree(node):
17
+ if node is None:
18
+ return None
19
+
20
+ return tree_form(str_form(node))
21
+
22
+ def __repr__(self):
23
+ return string_equation(str_form(self))
24
+
25
+ def __eq__(self, other):
26
+ if isinstance(other, int):
27
+ other = tree_form("d_" + str(other))
28
+ elif not isinstance(other, TreeNode):
29
+ return NotImplemented
30
+ return str_form(self) == str_form(other)
31
+
32
+ def __add__(self, other):
33
+ if isinstance(other, int):
34
+ other = tree_form("d_" + str(other))
35
+ return TreeNode("f_add", [self, other])
36
+
37
+ def __radd__(self, other):
38
+ return self.__add__(other)
39
+
40
+ def __mul__(self, other):
41
+ if isinstance(other, int):
42
+ other = tree_form("d_" + str(other))
43
+ return TreeNode("f_mul", [self, other])
44
+
45
+ def __rmul__(self, other):
46
+ return self.__mul__(other)
47
+
48
+ def __sub__(self, other):
49
+ if isinstance(other, int):
50
+ other = tree_form("d_" + str(other))
51
+ return self + (tree_form("d_-1") * other)
52
+
53
+ def __rsub__(self, other):
54
+ if isinstance(other, int):
55
+ other = tree_form("d_" + str(other))
56
+ return other + (tree_form("d_-1") * self)
57
+
58
+ def __pow__(self, other):
59
+ if isinstance(other, int):
60
+ other = tree_form("d_" + str(other))
61
+ return TreeNode("f_pow", [self, other])
62
+
63
+ def __rpow__(self, other):
64
+ if isinstance(other, int):
65
+ other = tree_form("d_" + str(other))
66
+ return TreeNode("f_pow", [other, self])
67
+
68
+ def __truediv__(self, other):
69
+ if isinstance(other, int):
70
+ other = tree_form("d_" + str(other))
71
+ return self * (other ** tree_form("d_-1"))
72
+
73
+ def __rtruediv__(self, other):
74
+ if isinstance(other, int):
75
+ other = tree_form("d_" + str(other))
76
+ return other * (self ** tree_form("d_-1"))
77
+
78
+ def __and__(self, other):
79
+ if isinstance(other, int):
80
+ other = tree_form("d_" + str(other))
81
+ return TreeNode("f_and", [self, other])
82
+
83
+ def __rand__(self, other):
84
+ return self.__and__(other)
85
+
86
+ def __or__(self, other):
87
+ if isinstance(other, int):
88
+ other = tree_form("d_" + str(other))
89
+ return TreeNode("f_or", [self, other])
90
+
91
+ def __ror__(self, other):
92
+ return self.__or__(other)
93
+
94
+ def __neg__(self):
95
+ return tree_form("d_-1") * self
96
+
97
+ def __hash__(self):
98
+ return hash(str_form(self))
99
+
100
+ def str_form(node):
101
+ def recursive_str(node, depth=0):
102
+ result = "{}{}".format(' ' * depth, node.name)
103
+ for child in node.children:
104
+ result += "\n" + recursive_str(child, depth + 1)
105
+ return result
106
+ if not isinstance(node, TreeNode):
107
+ return "d_"+str(node)
108
+ return recursive_str(node)
109
+ def replace(equation, find, r):
110
+ if str_form(equation) == str_form(find):
111
+ return r
112
+ col = TreeNode(equation.name, [])
113
+ for child in equation.children:
114
+ col.children.append(replace(child, find, r))
115
+ return col
116
+
117
+ def contain(equation, what):
118
+ if equation == what:
119
+ return True
120
+ if equation.children == []:
121
+ return False
122
+ return any(contain(child, what) for child in equation.children)
123
+ def remove_duplicates_custom(lst, rcustom):
124
+ result = []
125
+ for item in lst:
126
+ if not any(rcustom(item, x) for x in result):
127
+ result.append(item)
128
+ return result
129
+ def frac_to_tree(f):
130
+ if isinstance(f, int):
131
+ f = Fraction(f)
132
+ if f.numerator == 0:
133
+ return tree_form("d_0")
134
+ if f.numerator == 1:
135
+ if f.denominator == 1:
136
+ return tree_form("d_1")
137
+ return tree_form("d_"+str(f.denominator))**tree_form("d_-1")
138
+ if f.denominator == 1:
139
+ return tree_form("d_"+str(f.numerator))
140
+ else:
141
+ return tree_form("d_"+str(f.numerator))/tree_form("d_"+str(f.denominator))
142
+ def perfect_root(n, r):
143
+ if r <= 0 or (n < 0 and r % 2 == 0):
144
+ return False, None
145
+
146
+ lo = 0
147
+ hi = n if n > 1 else 1
148
+
149
+ while lo <= hi:
150
+ mid = lo + (hi - lo) // 2
151
+ pow_val = 1
152
+
153
+ for _ in range(r):
154
+ pow_val *= mid
155
+ if pow_val > n:
156
+ break
157
+
158
+ if pow_val == n:
159
+ return True, mid
160
+ elif pow_val < n:
161
+ lo = mid + 1
162
+ else:
163
+ hi = mid - 1
164
+
165
+ return False, None
166
+
167
+ def frac(eq):
168
+ if eq.name[:2] == "d_":
169
+ return Fraction(int(eq.name[2:]))
170
+ if eq.name == "f_add":
171
+ p = frac(eq.children[0])
172
+ if p is None:
173
+ return None
174
+ for child in eq.children[1:]:
175
+ tmp = frac(child)
176
+ if isinstance(tmp, Fraction):
177
+ p+= tmp
178
+ else:
179
+ return None
180
+ return p
181
+ if eq.name == "f_mul":
182
+ p = frac(eq.children[0])
183
+ if p is None:
184
+ return None
185
+ for child in eq.children[1:]:
186
+ tmp = frac(child)
187
+ if isinstance(tmp, Fraction):
188
+ p*= tmp
189
+ else:
190
+ return None
191
+ return p
192
+ if eq.name == "f_pow":
193
+ a = frac(eq.children[0])
194
+ b = frac(eq.children[1])
195
+ if a is None or b is None:
196
+ return None
197
+ if a == 0 and b <= 0:
198
+ return None
199
+ if b.denominator == 1:
200
+ return a ** b.numerator
201
+ found_c, c = perfect_root(a.numerator, b.denominator)
202
+ found_d, d = perfect_root(a.denominator, b.denominator)
203
+ if found_c and found_d:
204
+ return Fraction(c,d) ** b.numerator
205
+ return None
206
+ return None
207
+ def factor_generation(eq):
208
+ output = []
209
+ if eq.name != "f_mul":
210
+ eq = TreeNode("f_mul", [eq])
211
+ if eq.name == "f_mul":
212
+ for child in eq.children:
213
+ if child.name == "f_pow":
214
+ if child.children[1].name[:2] != "d_":
215
+ output.append(child)
216
+ continue
217
+ if frac(child.children[1]) is not None and frac(child.children[1]).denominator == 1:
218
+ n = int(child.children[1].name[2:])
219
+ if n < 0:
220
+ for i in range(-n):
221
+ out = factor_generation(child.children[0])
222
+ out = [x**-1 for x in out]
223
+ output += out
224
+ #output.append(child.children[0]**-1)
225
+ else:
226
+ for i in range(n):
227
+ output.append(child.children[0])
228
+ else:
229
+ output.append(child)
230
+ else:
231
+ output.append(child)
232
+
233
+ return output
234
+ import math
235
+
236
+ def compute(eq):
237
+ # Base case: leaf node
238
+ if eq.children == []:
239
+ if eq.name == "s_e":
240
+ return math.e
241
+ elif eq.name == "s_pi":
242
+ return math.pi
243
+ elif eq.name.startswith("d_"):
244
+ return float(eq.name[2:])
245
+ else:
246
+ return None
247
+
248
+ # Recursive case: compute child values
249
+ values = [compute(child) for child in eq.children]
250
+ if None in values:
251
+ return None
252
+ # Evaluate based on node type
253
+ if eq.name == "f_add":
254
+ return sum(values)
255
+ elif eq.name == "f_abs":
256
+ return math.fabs(values[0])
257
+ elif eq.name == "f_sub":
258
+ return values[0] - values[1]
259
+ elif eq.name == "f_rad":
260
+ return values[0] * math.pi / 180
261
+ elif eq.name == "f_mul":
262
+ result = 1.0
263
+ for v in values:
264
+ result *= v
265
+ return result
266
+ elif eq.name == "f_neg":
267
+ return -values[0]
268
+ elif eq.name == "f_div":
269
+ return values[0] / values[1]
270
+ elif eq.name == "f_pow":
271
+ return values[0] ** values[1]
272
+ elif eq.name == "f_sin":
273
+ return math.sin(values[0])
274
+ elif eq.name == "f_cos":
275
+ return math.cos(values[0])
276
+ elif eq.name == "f_tan":
277
+ return math.tan(values[0])
278
+ elif eq.name == "f_arcsin":
279
+ return math.asin(values[0])
280
+ elif eq.name == "f_arccos":
281
+ return math.acos(values[0])
282
+ elif eq.name == "f_arctan":
283
+ return math.atan(values[0])
284
+ elif eq.name == "f_log":
285
+ return math.log(values[0])
286
+ else:
287
+ return None
288
+
289
+ def num_dem(equation):
290
+ num = tree_form("d_1")
291
+ den = tree_form("d_1")
292
+ for item in factor_generation(equation):
293
+ if item.name == "f_pow":
294
+ c = frac(item.children[1])
295
+ if c is not None and c < 0:
296
+ t = frac_to_tree(-c)
297
+ if t == tree_form("d_1"):
298
+ den = den * item.children[0]
299
+ else:
300
+ den = den * item.children[0]**t
301
+ else:
302
+ den = den * item
303
+ else:
304
+ num = num*item
305
+ return num, den
306
+
307
+ def summation(lst):
308
+ if len(lst) == 0:
309
+ return tree_form("d_0")
310
+ s = lst[0]
311
+ for item in lst[1:]:
312
+ s += item
313
+ return s
314
+ def vlist(eq):
315
+ out = []
316
+ if eq.name[:2] == "v_":
317
+ out.append(eq.name)
318
+ for child in eq.children:
319
+ out += vlist(child)
320
+ return sorted(list(set(out)), key=lambda x: int(x[2:]))
321
+ def product(lst):
322
+ if lst == []:
323
+ return tree_form("d_1")
324
+ s = lst[0]
325
+ for item in lst[1:]:
326
+ s *= item
327
+ return s
328
+ def flatten_tree(node):
329
+ if not node.children:
330
+ return node
331
+ if node.name in ("f_add", "f_mul", "f_and", "f_or"):
332
+ merged_children = []
333
+ for child in node.children:
334
+ flattened_child = flatten_tree(child)
335
+ if flattened_child.name == node.name:
336
+ merged_children.extend(flattened_child.children)
337
+ else:
338
+ merged_children.append(flattened_child)
339
+ return TreeNode(node.name, merged_children)
340
+ else:
341
+ node.children = [flatten_tree(child) for child in node.children]
342
+ return node
343
+ def dowhile(eq, fx):
344
+ if eq is None:
345
+ return None
346
+ while True:
347
+ orig = eq.copy_tree()
348
+ eq2 = fx(eq)
349
+ if eq2 is None:
350
+ return None
351
+ eq = eq2.copy_tree()
352
+ if eq == orig:
353
+ return orig
354
+ def tree_form(tabbed_strings):
355
+ lines = tabbed_strings.split("\n")
356
+ root = TreeNode("Root")
357
+ current_level_nodes = {0: root}
358
+ stack = [root]
359
+ for line in lines:
360
+ level = line.count(' ')
361
+ node_name = line.strip()
362
+ node = TreeNode(node_name)
363
+ while len(stack) > level + 1:
364
+ stack.pop()
365
+ parent_node = stack[-1]
366
+ parent_node.children.append(node)
367
+ current_level_nodes[level] = node
368
+ stack.append(node)
369
+ return root.children[0]
370
+ def string_equation_helper(equation_tree):
371
+ if equation_tree.children == []:
372
+ if equation_tree.name[:2]=="g_":
373
+ return '"'+equation_tree.name[2:]+'"'
374
+ return equation_tree.name
375
+ extra = ""
376
+ if equation_tree.name == "f_neg":
377
+ return "-"+string_equation_helper(equation_tree.children[0])
378
+ if equation_tree.name == "f_not":
379
+ return "~"+string_equation_helper(equation_tree.children[0])
380
+ if equation_tree.name == "f_list":
381
+ return "["+",".join([string_equation_helper(child) for child in equation_tree.children])+"]"
382
+ if equation_tree.name == "f_index":
383
+ return string_equation_helper(equation_tree.children[0])+"["+",".join([string_equation_helper(child) for child in equation_tree.children[1:]])+"]"
384
+ s = "("
385
+ if len(equation_tree.children) == 1 or equation_tree.name[2:] in [chr(ord("A")+i) for i in range(26)]+["limitpinf", "subs", "try", "ref","limit", "integrate", "exist", "forall", "sum2", "int", "pdif", "dif", "A", "B", "C", "covariance", "sum"]:
386
+ s = equation_tree.name[2:] + s
387
+ sign = {"f_not":"~", "f_addw":"+", "f_mulw":"*", "f_intersection":"&", "f_union":"|", "f_sum2":",", "f_exist":",", "f_forall":",", "f_sum":",","f_covariance": ",", "f_B":",", "f_imply":"->", "f_ge":">=", "f_le":"<=", "f_gt":">", "f_lt":"<", "f_cosec":"?" , "f_equiv": "<->", "f_sec":"?", "f_cot": "?", "f_dot": ".", "f_circumcenter":"?", "f_transpose":"?", "f_exp":"?", "f_abs":"?", "f_log":"?", "f_and":"&", "f_or":"|", "f_sub":"-", "f_neg":"?", "f_inv":"?", "f_add": "+", "f_mul": "*", "f_pow": "^", "f_poly": ",", "f_div": "/", "f_sub": "-", "f_dif": ",", "f_sin": "?", "f_cos": "?", "f_tan": "?", "f_eq": "=", "f_sqrt": "?"}
388
+ arr = []
389
+ k = None
390
+ if equation_tree.name not in sign.keys():
391
+ k = ","
392
+ else:
393
+ k = sign[equation_tree.name]
394
+ for child in equation_tree.children:
395
+ arr.append(string_equation_helper(child.copy_tree()))
396
+ outfinal = s + k.join(arr) + ")"+extra
397
+
398
+ return outfinal.replace("+-", "-")
399
+ def string_equation(eq):
400
+ alpha = ["x", "y", "z"]+[chr(x+ord("a")) for x in range(0,23)]
401
+ beta = [chr(x+ord("A")) for x in range(0,26)]
402
+ eq = tree_form(eq)
403
+
404
+ for i, letter in enumerate(alpha):
405
+ eq = replace(eq, tree_form("v_"+str(i)), tree_form(letter))
406
+ for i, letter in enumerate(beta):
407
+ eq = replace(eq, tree_form("v_-"+str(i+1)), tree_form(letter))
408
+ for i in range(100, 150):
409
+ eq = replace(eq, tree_form("v_"+str(i)), tree_form("c"+str(i-100)))
410
+ eq = str_form(eq)
411
+
412
+ eq = eq.replace("d_", "")
413
+ eq = eq.replace("s_", "")
414
+ eq = eq.replace("v_", "")
415
+ eq = eq.replace("'", "")
416
+ outfinal = string_equation_helper(tree_form(eq))
417
+ if outfinal[0] == "(" and outfinal[-1] == ")":
418
+ return outfinal[1:-1]
419
+ return outfinal