mathai 0.4.0__py3-none-any.whl → 0.6.9__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 CHANGED
@@ -1,10 +1,15 @@
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
+
1
6
  from .expand import expand
2
7
 
3
8
  from .parser import parse
4
9
 
5
- from .printeq import printeq, printeq_log, printeq_str
10
+ from .printeq import printeq, printeq_str
6
11
 
7
- from .simplify import solve, simplify, solve2
12
+ from .simplify import simplify
8
13
 
9
14
  from .integrate import ref as integrate_save
10
15
  from .integrate import integrate_subs_main as integrate_subs
@@ -19,7 +24,9 @@ from .integrate import integrate_formula
19
24
  from .diff import diff
20
25
 
21
26
  from .factor import factor as factor1
22
- from .factor import factor2
27
+ from .factor import factor2, factor3
28
+ from .factor import rationalize_sqrt as rationalize
29
+ from .factor import merge_sqrt
23
30
  from .factor import factorconst as factor0
24
31
 
25
32
  from .fraction import fraction
@@ -28,19 +35,19 @@ from .inverse import inverse
28
35
 
29
36
  from .trig import trig0, trig1, trig2, trig3, trig4
30
37
 
31
- from .logic import logic0, logic1, logic2, logic3
38
+ from .logic import logic0, logic1, logic2, logic3, logic_n
32
39
 
33
- from .apart import apart
40
+ from .apart import apart, apart2
34
41
 
35
- from .console import console
42
+ from .limit import limit1, limit2, limit0, limit3
36
43
 
37
- from .limit import limit
44
+ from .univariate_inequality import wavycurvy, absolute, domain, handle_sqrt, prepare
45
+ from .bivariate_inequality import inequality_solve
38
46
 
39
- from .search import dfs_simplify as search0
40
-
41
- from .univariate_inequality import wavycurvy, absolute, domain, handle_sqrt
47
+ from .matrix import matrix_solve
42
48
 
43
49
  from .base import *
44
50
 
45
51
  from .tool import enclose_const
46
-
52
+ from .tool import poly_simplify
53
+ from .tool import longdiv
mathai/apart.py CHANGED
@@ -1,20 +1,28 @@
1
1
  from .linear import linear_solve
2
2
  from .expand import expand
3
3
  from .simplify import simplify
4
+
4
5
  from .diff import diff
5
6
  from .inverse import inverse
6
7
  from .base import *
7
8
  import math
8
- from .tool import poly, enclose_const
9
+ from .factor import factor2
10
+ from .tool import poly, enclose_const, longdiv
9
11
 
10
- def _apart(eq, v="v_0"):
12
+ def _apart(eq, v=None):
11
13
 
14
+ if v is None:
15
+ if len(vlist(eq)) == 0:
16
+ return eq
17
+ v = vlist(eq)[0]
12
18
  origv = vlist(eq)
13
- eq = simplify(eq)
19
+
14
20
  if eq.name != "f_mul":
15
21
  return eq
22
+
16
23
  if any("f_"+item in str_form(eq) for item in "sin cos tan log".split(" ")):
17
24
  return eq
25
+
18
26
  def exclude(eq):
19
27
  if eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]).denominator != 1:
20
28
  return False
@@ -42,8 +50,9 @@ def _apart(eq, v="v_0"):
42
50
  s = []
43
51
  facd = [simplify(x) for x in factor_generation(simplify(d))]
44
52
 
45
-
46
- facd2 = remove_duplicates_custom(facd, lambda m, n: simplify(m-n) == tree_form("d_0"))
53
+
54
+ facd2 = remove_duplicates_custom(facd, lambda m, n: simplify(expand(simplify(m-n))) == tree_form("d_0"))
55
+
47
56
  if len(facd2) == 1:
48
57
  return eq
49
58
  x = tree_form(v)
@@ -55,9 +64,10 @@ def _apart(eq, v="v_0"):
55
64
  g = countfac(facd, item)
56
65
  for n in range(int(g.name[2:])):
57
66
  n = n+1
58
- if n > 2:
67
+ if n > 3:
59
68
  return eq
60
69
  n = tree_form("d_"+str(n))
70
+
61
71
  l = len(poly(item, v))
62
72
  if l == 3:
63
73
  a = alloclst.pop(0)
@@ -81,6 +91,7 @@ def _apart(eq, v="v_0"):
81
91
  dem.append(item**n)
82
92
  s.append(a/item**n)
83
93
  else:
94
+
84
95
  return eq
85
96
  final3 = summation(s)
86
97
 
@@ -89,9 +100,9 @@ def _apart(eq, v="v_0"):
89
100
  final2 = []
90
101
  for i in range(len(num)):
91
102
  final2.append(product([dem[k] for k in range(len(dem)) if i != k])*num[i])
92
-
103
+
93
104
  final = summation(final2)
94
-
105
+
95
106
  s = simplify(TreeNode("f_eq", [final-eq2, tree_form("d_0")]))
96
107
 
97
108
  lst = poly(s.children[0], v)
@@ -101,13 +112,31 @@ def _apart(eq, v="v_0"):
101
112
  for item in lst:
102
113
  lst2+=vlist(item)
103
114
  origv = list(set(lst2)-set(origv))
115
+
104
116
  out = linear_solve(TreeNode("f_and", lst), [tree_form(item) for item in origv])
105
117
  for item in out.children:
106
118
 
107
119
  final3 = replace(final3, tree_form(list(set(vlist(item))&set(origv))[0]), inverse(item.children[0], list(set(vlist(item))&set(origv))[0]))
108
- return simplify(final3)
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])
109
133
  def apart(eq):
134
+ eq = factor2(simplify(eq))
110
135
  eq, fx = enclose_const(eq)
111
-
112
- eq = _apart(eq)
113
- return fx(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 CHANGED
@@ -1,24 +1,67 @@
1
1
  import copy
2
2
  from fractions import Fraction
3
+ def use(eq):
4
+ return TreeNode(eq.name, [use(child) for child in eq.children])
5
+ def use2(eq):
6
+ return use(tree_form(str_form(eq).replace("f_wmul", "f_mul")))
7
+ def contains_list_or_neg(node):
8
+ stack = [node]
9
+ while stack:
10
+ n = stack.pop()
11
+ if n.name == "f_list" or n.name.startswith("v_-"):
12
+ return True
13
+ stack.extend(n.children)
14
+ return False
3
15
 
4
16
  class TreeNode:
5
- def __init__(self, name, children=[]):
6
-
7
- children = [child.copy_tree() for child in children]
17
+ matmul = None
18
+
19
+ def __init__(self, name, children=None):
20
+ if children is None:
21
+ children = []
22
+
23
+ # copy once
24
+ children = copy.deepcopy(children)
8
25
  self.name = name
9
- if name in ["f_add", "f_mul"]:
10
- self.children = sorted(children, key=lambda x: str_form(x))
26
+
27
+ if name == "f_add" or (name == "f_mul" and TreeNode.matmul is None):
28
+ keyed = [(str_form(c), c) for c in children]
29
+ self.children = [c for _, c in sorted(keyed)]
30
+
31
+ elif name == "f_mul" and TreeNode.matmul == False:
32
+ sortable = []
33
+ fixed = []
34
+ for c in children:
35
+ if not contains_list_or_neg(c):
36
+ sortable.append(c)
37
+ else:
38
+ fixed.append(c)
39
+
40
+ if len(sortable) > 1:
41
+ sortable = TreeNode("f_dmul", list(sorted(sortable, key=lambda x: str_form(x))))
42
+ sortable.name = "f_mul"
43
+
44
+ elif len(sortable) == 1:
45
+ sortable = sortable[0]
46
+
47
+ if isinstance(sortable, TreeNode):
48
+ fixed.append(sortable)
49
+ if len(fixed) > 1:
50
+ self.name = "f_wmul"
51
+ elif len(fixed) == 1:
52
+ self.name = fixed[0].name
53
+ fixed = fixed[0].children
54
+
55
+
56
+ self.children = fixed
11
57
  else:
12
58
  self.children = children
13
59
 
60
+
14
61
  def fx(self, fxname):
15
62
  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
-
63
+ def copy_tree(self):
64
+ return copy.deepcopy(self)
22
65
  def __repr__(self):
23
66
  return string_equation(str_form(self))
24
67
 
@@ -126,11 +169,51 @@ def remove_duplicates_custom(lst, rcustom):
126
169
  if not any(rcustom(item, x) for x in result):
127
170
  result.append(item)
128
171
  return result
172
+ def frac_to_tree(f):
173
+ if isinstance(f, int):
174
+ f = Fraction(f)
175
+ if f.numerator == 0:
176
+ return tree_form("d_0")
177
+ if f.numerator == 1:
178
+ if f.denominator == 1:
179
+ return tree_form("d_1")
180
+ return tree_form("d_"+str(f.denominator))**tree_form("d_-1")
181
+ if f.denominator == 1:
182
+ return tree_form("d_"+str(f.numerator))
183
+ else:
184
+ return tree_form("d_"+str(f.numerator))/tree_form("d_"+str(f.denominator))
185
+ def perfect_root(n, r):
186
+ if r <= 0 or (n < 0 and r % 2 == 0):
187
+ return False, None
188
+
189
+ lo = 0
190
+ hi = n if n > 1 else 1
191
+
192
+ while lo <= hi:
193
+ mid = lo + (hi - lo) // 2
194
+ pow_val = 1
195
+
196
+ for _ in range(r):
197
+ pow_val *= mid
198
+ if pow_val > n:
199
+ break
200
+
201
+ if pow_val == n:
202
+ return True, mid
203
+ elif pow_val < n:
204
+ lo = mid + 1
205
+ else:
206
+ hi = mid - 1
207
+
208
+ return False, None
209
+
129
210
  def frac(eq):
130
211
  if eq.name[:2] == "d_":
131
212
  return Fraction(int(eq.name[2:]))
132
213
  if eq.name == "f_add":
133
214
  p = frac(eq.children[0])
215
+ if p is None:
216
+ return None
134
217
  for child in eq.children[1:]:
135
218
  tmp = frac(child)
136
219
  if isinstance(tmp, Fraction):
@@ -140,6 +223,8 @@ def frac(eq):
140
223
  return p
141
224
  if eq.name == "f_mul":
142
225
  p = frac(eq.children[0])
226
+ if p is None:
227
+ return None
143
228
  for child in eq.children[1:]:
144
229
  tmp = frac(child)
145
230
  if isinstance(tmp, Fraction):
@@ -150,23 +235,27 @@ def frac(eq):
150
235
  if eq.name == "f_pow":
151
236
  a = frac(eq.children[0])
152
237
  b = frac(eq.children[1])
153
- if isinstance(a, Fraction) and isinstance(b, Fraction) and b.denominator==1:
154
- if a == 0 and b <= 0:
155
- return None
156
- return a**b
157
- else:
238
+ if a is None or b is None:
239
+ return None
240
+ if a == 0 and b <= 0:
158
241
  return None
242
+ if b.denominator == 1:
243
+ return a ** b.numerator
244
+ found_c, c = perfect_root(a.numerator, b.denominator)
245
+ found_d, d = perfect_root(a.denominator, b.denominator)
246
+ if found_c and found_d:
247
+ return Fraction(c,d) ** b.numerator
248
+ return None
159
249
  return None
160
250
  def factor_generation(eq):
161
251
  output = []
162
252
  if eq.name != "f_mul":
163
- eq = TreeNode("f_mul", [eq])
253
+ tmp = TreeNode("f_mul", [])
254
+ tmp.children.append(eq)
255
+ eq = tmp
164
256
  if eq.name == "f_mul":
165
257
  for child in eq.children:
166
258
  if child.name == "f_pow":
167
- if child.children[0].name[:2] == "s_":
168
- output.append(child)
169
- continue
170
259
  if child.children[1].name[:2] != "d_":
171
260
  output.append(child)
172
261
  continue
@@ -174,7 +263,10 @@ def factor_generation(eq):
174
263
  n = int(child.children[1].name[2:])
175
264
  if n < 0:
176
265
  for i in range(-n):
177
- output.append(child.children[0]**-1)
266
+ out = factor_generation(child.children[0])
267
+ out = [x**-1 for x in out]
268
+ output += out
269
+ #output.append(child.children[0]**-1)
178
270
  else:
179
271
  for i in range(n):
180
272
  output.append(child.children[0])
@@ -205,11 +297,13 @@ def compute(eq):
205
297
  # Evaluate based on node type
206
298
  if eq.name == "f_add":
207
299
  return sum(values)
300
+ elif eq.name == "f_abs":
301
+ return math.fabs(values[0])
208
302
  elif eq.name == "f_sub":
209
303
  return values[0] - values[1]
210
304
  elif eq.name == "f_rad":
211
305
  return values[0] * math.pi / 180
212
- elif eq.name == "f_mul":
306
+ elif eq.name in ["f_wmul", "f_mul"]:
213
307
  result = 1.0
214
308
  for v in values:
215
309
  result *= v
@@ -241,16 +335,22 @@ def num_dem(equation):
241
335
  num = tree_form("d_1")
242
336
  den = tree_form("d_1")
243
337
  for item in factor_generation(equation):
244
-
245
- t = item
246
- if t.name == "f_pow" and "v_" not in str_form(t.children[1]) and compute(t.children[1]) < 0:
247
-
248
- den = den*item
338
+ if item.name == "f_pow":
339
+ c = frac(item.children[1])
340
+ if c is not None and c < 0:
341
+ t = frac_to_tree(-c)
342
+ if t == tree_form("d_1"):
343
+ den = den * item.children[0]
344
+ else:
345
+ den = den * item.children[0]**t
346
+ else:
347
+ den = den * item
249
348
  else:
250
349
  num = num*item
251
- return [num, tree_form("d_1")/den]
350
+ return num, den
351
+
252
352
  def summation(lst):
253
- if lst == []:
353
+ if len(lst) == 0:
254
354
  return tree_form("d_0")
255
355
  s = lst[0]
256
356
  for item in lst[1:]:
@@ -270,28 +370,31 @@ def product(lst):
270
370
  for item in lst[1:]:
271
371
  s *= item
272
372
  return s
273
- def flatten_tree(node):
373
+ def flatten_tree(node, add=[]):
274
374
  if not node.children:
275
375
  return node
276
- if node.name in ("f_add", "f_mul", "f_and", "f_or"):
376
+ ad = []
377
+ if node.name in ["f_add", "f_mul", "f_and", "f_or", "f_wmul"]:
277
378
  merged_children = []
278
379
  for child in node.children:
279
- flattened_child = flatten_tree(child)
380
+ flattened_child = flatten_tree(child, add)
280
381
  if flattened_child.name == node.name:
281
382
  merged_children.extend(flattened_child.children)
282
383
  else:
283
384
  merged_children.append(flattened_child)
284
385
  return TreeNode(node.name, merged_children)
285
386
  else:
286
- node.children = [flatten_tree(child) for child in node.children]
387
+ node.children = [flatten_tree(child, add) for child in node.children]
287
388
  return node
288
389
  def dowhile(eq, fx):
390
+ if eq is None:
391
+ return None
289
392
  while True:
290
- orig = eq.copy_tree()
393
+ orig = copy.deepcopy(eq)
291
394
  eq2 = fx(eq)
292
395
  if eq2 is None:
293
396
  return None
294
- eq = eq2.copy_tree()
397
+ eq = copy.deepcopy(eq2)
295
398
  if eq == orig:
296
399
  return orig
297
400
  def tree_form(tabbed_strings):
@@ -325,9 +428,9 @@ def string_equation_helper(equation_tree):
325
428
  if equation_tree.name == "f_index":
326
429
  return string_equation_helper(equation_tree.children[0])+"["+",".join([string_equation_helper(child) for child in equation_tree.children[1:]])+"]"
327
430
  s = "("
328
- if len(equation_tree.children) == 1 or equation_tree.name[2:] in [chr(ord("A")+i) for i in range(26)]+["subs", "try", "ref", "integrate", "exist", "forall", "sum2", "int", "pdif", "dif", "A", "B", "C", "covariance", "sum"]:
431
+ 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"]:
329
432
  s = equation_tree.name[2:] + s
330
- 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": "?"}
433
+ sign = {"f_not":"~", "f_wadd":"+", "f_wmul":"*", "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": "?"}
331
434
  arr = []
332
435
  k = None
333
436
  if equation_tree.name not in sign.keys():
@@ -335,7 +438,7 @@ def string_equation_helper(equation_tree):
335
438
  else:
336
439
  k = sign[equation_tree.name]
337
440
  for child in equation_tree.children:
338
- arr.append(string_equation_helper(child.copy_tree()))
441
+ arr.append(string_equation_helper(copy.deepcopy(child)))
339
442
  outfinal = s + k.join(arr) + ")"+extra
340
443
 
341
444
  return outfinal.replace("+-", "-")