mathai 0.6.8__py3-none-any.whl → 0.7.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 CHANGED
@@ -7,7 +7,7 @@ from .expand import expand
7
7
 
8
8
  from .parser import parse
9
9
 
10
- from .printeq import printeq, printeq_log, printeq_str
10
+ from .printeq import printeq, printeq_str
11
11
 
12
12
  from .simplify import simplify
13
13
 
mathai/base.py CHANGED
@@ -2,6 +2,8 @@ import copy
2
2
  from fractions import Fraction
3
3
  def use(eq):
4
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")))
5
7
  def contains_list_or_neg(node):
6
8
  stack = [node]
7
9
  while stack:
@@ -10,9 +12,10 @@ def contains_list_or_neg(node):
10
12
  return True
11
13
  stack.extend(n.children)
12
14
  return False
15
+
13
16
  class TreeNode:
14
17
  matmul = None
15
-
18
+
16
19
  def __init__(self, name, children=None):
17
20
  if children is None:
18
21
  children = []
@@ -247,7 +250,9 @@ def frac(eq):
247
250
  def factor_generation(eq):
248
251
  output = []
249
252
  if eq.name != "f_mul":
250
- eq = TreeNode("f_mul", [eq])
253
+ tmp = TreeNode("f_mul", [])
254
+ tmp.children.append(eq)
255
+ eq = tmp
251
256
  if eq.name == "f_mul":
252
257
  for child in eq.children:
253
258
  if child.name == "f_pow":
@@ -365,21 +370,23 @@ def product(lst):
365
370
  for item in lst[1:]:
366
371
  s *= item
367
372
  return s
368
- def flatten_tree(node, add=[]):
373
+ def flatten_tree(node):
374
+ if node is None:
375
+ return None
369
376
  if not node.children:
370
377
  return node
371
378
  ad = []
372
379
  if node.name in ["f_add", "f_mul", "f_and", "f_or", "f_wmul"]:
373
380
  merged_children = []
374
381
  for child in node.children:
375
- flattened_child = flatten_tree(child, add)
382
+ flattened_child = flatten_tree(child)
376
383
  if flattened_child.name == node.name:
377
384
  merged_children.extend(flattened_child.children)
378
385
  else:
379
386
  merged_children.append(flattened_child)
380
387
  return TreeNode(node.name, merged_children)
381
388
  else:
382
- node.children = [flatten_tree(child, add) for child in node.children]
389
+ node.children = [flatten_tree(child) for child in node.children]
383
390
  return node
384
391
  def dowhile(eq, fx):
385
392
  if eq is None:
mathai/expand.py CHANGED
@@ -1,129 +1,95 @@
1
- import itertools
2
1
  from .base import *
3
2
  from .simplify import simplify
4
- '''
5
- def _expand(equation):
6
- eq = equation
7
- eq.children = [_expand(flatten_tree(child)) for child in eq.children]
8
- if eq.name == "f_pow":
9
- n = frac(eq.children[1])
10
- if n is not None and n.denominator == 1 and n.numerator > 1:
11
- power_children = []
12
- for i in range(n.numerator):
13
- power_children.append(eq.children[0])
14
- return _expand(flatten_tree(TreeNode("f_mul", power_children)))
15
- if eq.name == "f_mul":
16
- lone_children = tree_form("d_1")
17
- bracket_children = []
18
- for i in range(len(eq.children)-1,-1,-1):
19
- if eq.children[i].name == "f_add":
20
- bracket_children.append(eq.children[i])
21
- elif eq.children[i].name == "f_pow" and eq.children[i].children[0].name == "f_add":
22
- n = frac(eq.children[i].children[1])
23
- if n is not None and n.denominator == 1 and n.numerator > 1:
24
- for j in range(n.numerator):
25
- bracket_children.append(eq.children[i].children[0])
26
- else:
27
- lone_children = lone_children * eq.children[i]
28
- else:
29
- lone_children = lone_children * eq.children[i]
30
- lone_children = simplify(lone_children)
31
- while bracket_children != []:
32
- tmp = tree_form("d_0")
33
- for i in range(len(bracket_children[0].children)):
34
- if lone_children.name == "f_add":
35
- for j in range(len(lone_children.children)):
36
- tmp = tmp + bracket_children[0].children[i] * lone_children.children[j]
37
- else:
38
- tmp = tmp + lone_children * bracket_children[0].children[i]
39
- lone_children = flatten_tree(simplify(tmp))
40
- bracket_children.pop(0)
41
- return lone_children
42
- return eq
43
- '''
44
- def is_expandable(child):
45
- if child.name == "f_add":
46
- return True
47
- if child.name == "f_pow" and child.children[0].name == "f_add":
48
- n = frac(child.children[1])
49
- return n is not None and n.denominator == 1 and n.numerator > 1
50
- return False
51
-
52
-
53
- def expand_terms(child):
54
- if child.name == "f_add":
55
- return child.children
56
- n = frac(child.children[1]).numerator
57
- return child.children[0].children * n
58
-
59
-
60
- def _expand(equation):
61
- stack = [(equation, 0, [])]
62
-
63
- while stack:
64
- node, idx, done = stack.pop()
65
-
66
- if idx >= len(node.children):
67
- node.children = done
68
-
69
- # ===== f_pow =====
70
- if node.name == "f_pow":
71
- n = frac(node.children[1])
72
- if n and n.denominator == 1 and n.numerator > 1:
73
- node = flatten_tree(
74
- TreeNode("f_mul", [node.children[0]] * n.numerator)
75
- )
76
- stack.append((node, 0, []))
77
- continue
78
-
79
- # ===== f_mul =====
80
- elif node.name == "f_mul":
81
- children = node.children
82
- k = len(children)
83
-
84
- # ---- find expandable index (L→R, then R→L) ----
85
- idxs = list(range(k)) + list(reversed(range(k)))
86
- seen = set()
87
- expand_i = None
88
-
89
- for i in idxs:
90
- if i in seen:
91
- continue
92
- seen.add(i)
93
- if is_expandable(children[i]):
94
- expand_i = i
95
- break
96
-
97
- if expand_i is not None:
98
- left = children[:expand_i]
99
- right = children[expand_i + 1:]
100
- expandable = children[expand_i]
101
-
102
- out = tree_form("d_0")
103
- for term in expand_terms(expandable):
104
- prod = term
105
- for r in right:
106
- prod = prod * r
107
- for l in reversed(left):
108
- prod = l * prod
109
- out = out + prod
110
-
111
- node = flatten_tree(simplify(out))
112
-
113
- # ===== return =====
114
- if stack:
115
- parent, pidx, acc = stack.pop()
116
- acc.append(node)
117
- stack.append((parent, pidx + 1, acc))
118
- else:
119
- return node
120
-
121
- else:
122
- stack.append((node, idx, done))
123
- child = flatten_tree(node.children[idx])
124
- stack.append((child, 0, []))
3
+ import itertools
4
+
5
+ def eliminate_powers(node):
6
+ if not node.children:
7
+ return node
8
+
9
+ node.children = [eliminate_powers(c) for c in node.children]
10
+
11
+ if node.name == "f_pow":
12
+ base, exp = node.children
13
+ n = frac(exp)
14
+
15
+ # Only expand positive integer powers
16
+ if not (n and n.denominator == 1 and n.numerator > 1):
17
+ return node
18
+
19
+ n = n.numerator
20
+
21
+ # ---- Multinomial expansion ----
22
+ if base.name == "f_add":
23
+ terms = []
24
+ for combo in itertools.product(base.children, repeat=n):
25
+ prod = combo[0]
26
+ for c in combo[1:]:
27
+ prod = prod * c
28
+ terms.append(prod)
29
+ return simplify(TreeNode("f_add", terms))
30
+
31
+ # ---- Fallback: simple power ----
32
+ return TreeNode("f_mul", [base] * n)
33
+
34
+ return node
35
+
36
+
37
+
38
+ # =====================================================
39
+ # Phase 2: Single distributive rewrite (DEEPEST FIRST)
40
+ # =====================================================
41
+
42
+ def expand_once(node):
43
+ """
44
+ Performs exactly ONE distributive expansion.
45
+ Deepest-first (post-order).
46
+ """
47
+
48
+ # ---- recurse FIRST (this is the fix) ----
49
+ for i, c in enumerate(node.children):
50
+ new, changed = expand_once(c)
51
+ if changed:
52
+ node.children[i] = new
53
+ return node, True
54
+
55
+ # ---- now try expanding at this node ----
56
+ if node.name == "f_mul":
57
+ for i, child in enumerate(node.children):
58
+ if child.name == "f_add":
59
+ left = node.children[:i]
60
+ right = node.children[i+1:]
61
+
62
+ terms = []
63
+ for t in child.children:
64
+ prod = t
65
+ for r in right:
66
+ prod = prod * r
67
+ for l in reversed(left):
68
+ prod = l * prod
69
+ terms.append(prod)
70
+
71
+ return TreeNode("f_add", terms), True
72
+
73
+ return node, False
74
+
75
+
76
+ # =====================================================
77
+ # Phase 3: Global fixed-point driver
78
+ # =====================================================
125
79
 
126
80
  def expand(eq):
127
- if TreeNode.matmul == True:
81
+ orig = TreeNode.matmul
82
+ eq = simplify(eq)
83
+ if TreeNode.matmul is not None:
84
+ TreeNode.matmul = True
128
85
  eq = tree_form(str_form(eq).replace("f_wmul", "f_mul"))
129
- return _expand(eq)
86
+ eq = flatten_tree(eq)
87
+ eq = eliminate_powers(eq)
88
+ while True:
89
+ eq = flatten_tree(eq)
90
+ eq, changed = expand_once(eq)
91
+ if not changed:
92
+ break
93
+ eq =simplify(eq)
94
+ TreeNode.matmul = orig
95
+ return eq
mathai/factor.py CHANGED
@@ -8,7 +8,7 @@ from .expand import expand
8
8
  import math
9
9
  from .tool import poly
10
10
  from .fraction import fraction
11
- from .printeq import printeq
11
+
12
12
  from collections import Counter
13
13
  def multiset_intersection(*lists):
14
14
  counters = list(map(Counter, lists))
mathai/matrix.py CHANGED
@@ -215,14 +215,13 @@ def fold_wmul(root):
215
215
  return newnode[root]
216
216
 
217
217
  def flat(eq):
218
- return flatten_tree(eq, ["f_wmul"])
218
+ return flatten_tree(eq)
219
219
  def use(eq):
220
220
  return TreeNode(eq.name, [use(child) for child in eq.children])
221
221
  def _matrix_solve(eq):
222
222
  if TreeNode.matmul == True:
223
223
  TreeNode.matmul = False
224
- eq = use(eq)
225
- eq = dowhile(eq, lambda x: fold_wmul(flat(x)))
224
+ eq = dowhile(eq, lambda x: fold_wmul(use(flat(x))))
226
225
  TreeNode.matmul = True
227
226
  return eq
228
227
  def matrix_solve(eq):
mathai/parser.py CHANGED
@@ -154,7 +154,7 @@ def parse(equation, funclist=None):
154
154
  return tree_node
155
155
 
156
156
  tree_node = rfx(tree_node)
157
- tree_node = flatten_tree(tree_node, ["f_wmul"])
157
+ tree_node = flatten_tree(tree_node)
158
158
  if TreeNode.matmul == True:
159
159
  TreeNode.matmul = False
160
160
  tree_node = use(tree_form(str_form(tree_node).replace("f_w","f_")))
mathai/printeq.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from .base import *
2
+ from .factor import merge_sqrt
2
3
  from .simplify import simplify
3
4
  import copy
4
5
  from fractions import Fraction
@@ -24,11 +25,13 @@ def abstractexpr(eq):
24
25
  return TreeNode(eq.name, [abstractexpr(child) for child in eq.children])
25
26
 
26
27
  def printeq_str(eq):
27
- return str(dowhile(eq, abstractexpr))
28
+ if eq is None:
29
+ return None
30
+ eq = merge_sqrt(eq)
31
+ return string_equation(str_form(dowhile(eq, abstractexpr)))
32
+ def printeq_obj(self):
33
+ return printeq_str(self)
28
34
 
29
35
  def printeq(eq):
30
36
  print(printeq_str(eq))
31
-
32
- def printeq_log(lst):
33
- for item in lst:
34
- print(" "*item[0] + item[1])
37
+ TreeNode.__repr__ = printeq_obj
mathai/simplify.py CHANGED
@@ -15,9 +15,12 @@ def convert_to_basic(node):
15
15
  return node
16
16
 
17
17
  def clear_div(eq, denom):
18
+
18
19
  lst = factor_generation(eq)
20
+
19
21
  if tree_form("d_0") in lst:
20
22
  return tree_form("d_0"), True
23
+
21
24
  lst3 = []
22
25
  for item in lst:
23
26
  if "v_" not in str_form(item) and compute(item) < 0:
@@ -33,10 +36,12 @@ def clear_div(eq, denom):
33
36
  eq2.append(item)
34
37
  else:
35
38
  eq3.append(item)
39
+
36
40
  if eq3 == []:
37
41
  return product(eq2), True
38
42
  return product(eq3), sign
39
43
  lst4 = []
44
+
40
45
  for item in lst:
41
46
  if item.name == "f_pow":
42
47
  tmp = frac(item.children[1])
@@ -44,10 +49,12 @@ def clear_div(eq, denom):
44
49
  lst4.append(item)
45
50
  else:
46
51
  lst4.append(item)
52
+
47
53
  lst2 = []
48
54
  for item in lst4:
49
55
  if frac(item) is None:#"v_" in str_form(item):
50
56
  lst2.append(item)
57
+
51
58
  if lst2 == []:
52
59
  return product(lst4), sign
53
60
  return product(lst2), sign
@@ -503,23 +510,28 @@ def simplify(eq, basic=True):
503
510
  orig = TreeNode.matmul
504
511
  if TreeNode.matmul == True:
505
512
  TreeNode.matmul = False
513
+ if TreeNode.matmul == False:
506
514
  eq = use(tree_form(str_form(eq).replace("f_w","f_")))
507
515
 
508
516
  if eq.name == "f_and" or eq.name == "f_not" or eq.name == "f_or":
509
517
  new_children = []
510
518
  for child in eq.children:
511
519
  new_children.append(simplify(child))
520
+ TreeNode.matmul = orig
512
521
  return TreeNode(eq.name, new_children)
513
522
  if eq.name[2:] in "gt ge lt le eq".split(" "):
514
523
  denom = eq.name != "f_eq"
515
524
  tmp2 = simplify(eq.children[0] - eq.children[1])
516
525
  tmp, denom = clear_div(tmp2, denom)
517
526
  tmp = simplify(tmp)
527
+
518
528
  value2 = eq.name[2:]
519
529
  if denom is False:
520
530
  value2 = {"ge":"le", "le":"ge", "gt":"lt", "lt":"gt", "eq":"eq"}[value2]
521
531
  value2 = "f_"+value2
522
- return TreeNode(value2, [tmp, tree_form("d_0")])
532
+ out = TreeNode(value2, [tmp, tree_form("d_0")])
533
+ TreeNode.matmul = orig
534
+ return out
523
535
  eq = flatten_tree(eq)
524
536
  if basic:
525
537
  eq = convert_to_basic(eq)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 0.6.8
3
+ Version: 0.7.0
4
4
  Summary: Mathematics solving Ai tailored to NCERT
5
5
  Home-page: https://github.com/infinity390/mathai4
6
6
  Author: educated indians are having a low iq and are good for nothing
@@ -1,28 +1,28 @@
1
- mathai/__init__.py,sha256=gzddzgNCG3Bg5BnqrDYvO71SzK4hu9fbo4nGEaDaG5Q,1554
1
+ mathai/__init__.py,sha256=Mv0vNdV-FHKS6MzAsnHsE0eBtSkCUq0nc9tUgCWxbFo,1541
2
2
  mathai/apart.py,sha256=VSS3khE9PNuxiRvdU5JDl4IN-KJBSIFjwR17pkhviXI,4197
3
- mathai/base.py,sha256=9TfeBem7rrPwuJAEhrD-a5Mqzd9a0z-5aDa90Sl6LHg,15655
3
+ mathai/base.py,sha256=hRiJWS94asWl-t11eGrVCEhZqIub0T-8S_Eqmlun6mI,15819
4
4
  mathai/bivariate_inequality.py,sha256=Da-A1kqVynR0tNOlEI7GSTf5T2vNkcF4etL9-EoyPJg,11415
5
5
  mathai/console.py,sha256=Sn58iwYE79MLEh67s8X3q6vZjw6g7f9XM1T8_dBBR2o,3048
6
6
  mathai/diff.py,sha256=RSTwlfeddvYXUDShCeRdcPjsmAS8Vf5OkYJAaUBPaiM,3060
7
- mathai/expand.py,sha256=Bh9slVYXV9OAPSpTyuFWKVlJXqnN4eAF2z6y6MFjdGo,4799
8
- mathai/factor.py,sha256=4NF2xep0TpS307Z8WaFGmVSjfDGjlpLUuzFJAJKjJn4,12522
7
+ mathai/expand.py,sha256=NCe4LfM3-ndW78Zg8ZjlEVujb3-lG7_0H81ncRQizvw,2760
8
+ mathai/factor.py,sha256=3wcmZOGUqMlLj4v2DA14ZLqEQ7khavOi7PjZJU6VX40,12494
9
9
  mathai/fraction.py,sha256=88xvRpDGfFi8tbe1QIyejdSP91HcErrN4VS2MxzbhrY,4392
10
10
  mathai/integrate.py,sha256=C_lqYgQN4UiriCb_LDkpwtKx7XJhp_K8T9skCkxWqas,17208
11
11
  mathai/inverse.py,sha256=ya7P8WjzfaAL3UXL7xqOh5GaIsXLDZ-F6lZFy3IEgaQ,2931
12
12
  mathai/limit.py,sha256=9F8i9UZh2xb-V8A5Sd1gdhDf9c2RFgpE1GdNn9MvbWI,5703
13
13
  mathai/linear.py,sha256=viGlPU8BPrjLWHlyNUvnfPHNH5d4ZBImiQMdyXaKGg0,5702
14
14
  mathai/logic.py,sha256=Ndz4Fd6aNCmzFlqoPyyIpSmV_BXmYHsurePjLyZJoNc,9809
15
- mathai/matrix.py,sha256=05GEi6K3hyu3UP_CFZfPnwDVIB52YGmlzCtCoZPh_iw,7305
15
+ mathai/matrix.py,sha256=sIusSmZN0Y6k4TovI5L6Hepls9i7FPRjA3CZIU4X4_w,7276
16
16
  mathai/ode.py,sha256=zxxTXAOpt7oSsfpgI4vHsCWKXevmM96ZOBZWWs-vj8Y,4801
17
- mathai/parser.py,sha256=nEAdSSJeapBOhvjbkXJFtCEBU8izajXZAITV8rbslic,7314
17
+ mathai/parser.py,sha256=3cBl7DhqL275gqXszET5zC85O9v3XKxRPc2EaOigAns,7302
18
18
  mathai/parsetab.py,sha256=TL-4jvRM_Tx6ipwet8CFJc2DkjR4tGsbrGF_r4IC8xI,9651
19
- mathai/printeq.py,sha256=MKsR6-qXig80R07vLnFPYHQMeS41FrMVj3n3arrhJpQ,1329
20
- mathai/simplify.py,sha256=J4M81rOuzgOrRElKAFR1dx1BD7zK2CfmgdWw8z-az2w,19796
19
+ mathai/printeq.py,sha256=4UgLJo-vV_YlVw_3QUQY_jQMHrFnG-ZKAyVZsd7yD6o,1450
20
+ mathai/simplify.py,sha256=VsUw89U3FqSpD3mMUGM0pr0dZ__MDQOBD8maaB7MDBY,19973
21
21
  mathai/structure.py,sha256=wrU7kqphSN7CqaVffyHHXD2-3t5My_Z_TtYFoUe_lTU,4099
22
22
  mathai/tool.py,sha256=ozcXTXLbKUnyPM9r9kz9M43YA2CBcWezcqLZfEs8rpc,6051
23
23
  mathai/trig.py,sha256=fnBbfiopcQzFg4ya1BoO5M0X_aCBnse2bjnKh1juw4I,11223
24
24
  mathai/univariate_inequality.py,sha256=LPFdWgC1y5zBwnsy1wwZxj-yP_SbqFDhCmTTzhuwoiY,16469
25
- mathai-0.6.8.dist-info/METADATA,sha256=qlUlg0g6-rOvYKNeanb7r4GDXdsOJYuN6qP_Jrd94gY,7103
26
- mathai-0.6.8.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
27
- mathai-0.6.8.dist-info/top_level.txt,sha256=ROP4l3OhGYw3ihkQGASr18xM9GsK4z3_6whV5AyXLwE,7
28
- mathai-0.6.8.dist-info/RECORD,,
25
+ mathai-0.7.0.dist-info/METADATA,sha256=GrlB2OU2Qg4SXWpTvXeUaW9jobvWSlXyj66iSMkBr8Q,7103
26
+ mathai-0.7.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
27
+ mathai-0.7.0.dist-info/top_level.txt,sha256=ROP4l3OhGYw3ihkQGASr18xM9GsK4z3_6whV5AyXLwE,7
28
+ mathai-0.7.0.dist-info/RECORD,,
File without changes