mathai 0.6.7__tar.gz → 0.6.9__tar.gz

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.
Files changed (34) hide show
  1. {mathai-0.6.7 → mathai-0.6.9}/PKG-INFO +1 -1
  2. {mathai-0.6.7 → mathai-0.6.9}/mathai/__init__.py +1 -1
  3. {mathai-0.6.7 → mathai-0.6.9}/mathai/base.py +9 -2
  4. mathai-0.6.9/mathai/expand.py +95 -0
  5. {mathai-0.6.7 → mathai-0.6.9}/mathai/factor.py +1 -1
  6. {mathai-0.6.7 → mathai-0.6.9}/mathai/matrix.py +5 -1
  7. {mathai-0.6.7 → mathai-0.6.9}/mathai/parser.py +1 -2
  8. {mathai-0.6.7 → mathai-0.6.9}/mathai/printeq.py +8 -5
  9. {mathai-0.6.7 → mathai-0.6.9}/mathai/simplify.py +19 -1
  10. {mathai-0.6.7 → mathai-0.6.9}/mathai.egg-info/PKG-INFO +1 -1
  11. {mathai-0.6.7 → mathai-0.6.9}/setup.py +1 -1
  12. mathai-0.6.7/mathai/expand.py +0 -124
  13. {mathai-0.6.7 → mathai-0.6.9}/README.md +0 -0
  14. {mathai-0.6.7 → mathai-0.6.9}/mathai/apart.py +0 -0
  15. {mathai-0.6.7 → mathai-0.6.9}/mathai/bivariate_inequality.py +0 -0
  16. {mathai-0.6.7 → mathai-0.6.9}/mathai/console.py +0 -0
  17. {mathai-0.6.7 → mathai-0.6.9}/mathai/diff.py +0 -0
  18. {mathai-0.6.7 → mathai-0.6.9}/mathai/fraction.py +0 -0
  19. {mathai-0.6.7 → mathai-0.6.9}/mathai/integrate.py +0 -0
  20. {mathai-0.6.7 → mathai-0.6.9}/mathai/inverse.py +0 -0
  21. {mathai-0.6.7 → mathai-0.6.9}/mathai/limit.py +0 -0
  22. {mathai-0.6.7 → mathai-0.6.9}/mathai/linear.py +0 -0
  23. {mathai-0.6.7 → mathai-0.6.9}/mathai/logic.py +0 -0
  24. {mathai-0.6.7 → mathai-0.6.9}/mathai/ode.py +0 -0
  25. {mathai-0.6.7 → mathai-0.6.9}/mathai/parsetab.py +0 -0
  26. {mathai-0.6.7 → mathai-0.6.9}/mathai/structure.py +0 -0
  27. {mathai-0.6.7 → mathai-0.6.9}/mathai/tool.py +0 -0
  28. {mathai-0.6.7 → mathai-0.6.9}/mathai/trig.py +0 -0
  29. {mathai-0.6.7 → mathai-0.6.9}/mathai/univariate_inequality.py +0 -0
  30. {mathai-0.6.7 → mathai-0.6.9}/mathai.egg-info/SOURCES.txt +0 -0
  31. {mathai-0.6.7 → mathai-0.6.9}/mathai.egg-info/dependency_links.txt +0 -0
  32. {mathai-0.6.7 → mathai-0.6.9}/mathai.egg-info/requires.txt +0 -0
  33. {mathai-0.6.7 → mathai-0.6.9}/mathai.egg-info/top_level.txt +0 -0
  34. {mathai-0.6.7 → mathai-0.6.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 0.6.7
3
+ Version: 0.6.9
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
@@ -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
 
@@ -1,5 +1,9 @@
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")))
3
7
  def contains_list_or_neg(node):
4
8
  stack = [node]
5
9
  while stack:
@@ -8,9 +12,10 @@ def contains_list_or_neg(node):
8
12
  return True
9
13
  stack.extend(n.children)
10
14
  return False
15
+
11
16
  class TreeNode:
12
17
  matmul = None
13
-
18
+
14
19
  def __init__(self, name, children=None):
15
20
  if children is None:
16
21
  children = []
@@ -245,7 +250,9 @@ def frac(eq):
245
250
  def factor_generation(eq):
246
251
  output = []
247
252
  if eq.name != "f_mul":
248
- eq = TreeNode("f_mul", [eq])
253
+ tmp = TreeNode("f_mul", [])
254
+ tmp.children.append(eq)
255
+ eq = tmp
249
256
  if eq.name == "f_mul":
250
257
  for child in eq.children:
251
258
  if child.name == "f_pow":
@@ -0,0 +1,95 @@
1
+ from .base import *
2
+ from .simplify import simplify
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
+ # =====================================================
79
+
80
+ def expand(eq):
81
+ orig = TreeNode.matmul
82
+ eq = simplify(eq)
83
+ if TreeNode.matmul is not None:
84
+ TreeNode.matmul = True
85
+ eq = tree_form(str_form(eq).replace("f_wmul", "f_mul"))
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
@@ -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))
@@ -70,6 +70,10 @@ def contains_neg(node):
70
70
  return True
71
71
  # ---------- multiplication (fully simplified) ----------
72
72
  def multiply(left,right):
73
+ if left == tree_form("d_1"):
74
+ return right
75
+ if right == tree_form("d_1"):
76
+ return left
73
77
  left2, right2 = left, right
74
78
  if left2.name != "f_pow":
75
79
  left2 = left2 ** 1
@@ -217,7 +221,7 @@ def use(eq):
217
221
  def _matrix_solve(eq):
218
222
  if TreeNode.matmul == True:
219
223
  TreeNode.matmul = False
220
- eq = dowhile(eq, lambda x: fold_wmul(flat(x)))
224
+ eq = dowhile(eq, lambda x: fold_wmul(use(flat(x))))
221
225
  TreeNode.matmul = True
222
226
  return eq
223
227
  def matrix_solve(eq):
@@ -152,8 +152,7 @@ def parse(equation, funclist=None):
152
152
  return tree_form("v_" + str(int(tree_node.name[3:])+100))
153
153
  tree_node.children = [rfx(child) for child in tree_node.children]
154
154
  return tree_node
155
- def use(eq):
156
- return TreeNode(eq.name, [use(child) for child in eq.children])
155
+
157
156
  tree_node = rfx(tree_node)
158
157
  tree_node = flatten_tree(tree_node, ["f_wmul"])
159
158
  if TreeNode.matmul == True:
@@ -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
@@ -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
@@ -500,23 +507,34 @@ def solve3(eq):
500
507
  def simplify(eq, basic=True):
501
508
  if eq is None:
502
509
  return None
510
+ orig = TreeNode.matmul
511
+ if TreeNode.matmul == True:
512
+ TreeNode.matmul = False
513
+ if TreeNode.matmul == False:
514
+ eq = use(tree_form(str_form(eq).replace("f_w","f_")))
515
+
503
516
  if eq.name == "f_and" or eq.name == "f_not" or eq.name == "f_or":
504
517
  new_children = []
505
518
  for child in eq.children:
506
519
  new_children.append(simplify(child))
520
+ TreeNode.matmul = orig
507
521
  return TreeNode(eq.name, new_children)
508
522
  if eq.name[2:] in "gt ge lt le eq".split(" "):
509
523
  denom = eq.name != "f_eq"
510
524
  tmp2 = simplify(eq.children[0] - eq.children[1])
511
525
  tmp, denom = clear_div(tmp2, denom)
512
526
  tmp = simplify(tmp)
527
+
513
528
  value2 = eq.name[2:]
514
529
  if denom is False:
515
530
  value2 = {"ge":"le", "le":"ge", "gt":"lt", "lt":"gt", "eq":"eq"}[value2]
516
531
  value2 = "f_"+value2
517
- return TreeNode(value2, [tmp, tree_form("d_0")])
532
+ out = TreeNode(value2, [tmp, tree_form("d_0")])
533
+ TreeNode.matmul = orig
534
+ return out
518
535
  eq = flatten_tree(eq)
519
536
  if basic:
520
537
  eq = convert_to_basic(eq)
521
538
  eq = solve3(eq)
539
+ TreeNode.matmul = orig
522
540
  return eq
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 0.6.7
3
+ Version: 0.6.9
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
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="mathai",
5
- version="0.6.7",
5
+ version="0.6.9",
6
6
  description="Mathematics solving Ai tailored to NCERT",
7
7
  long_description=open("README.md").read(),
8
8
  long_description_content_type="text/markdown",
@@ -1,124 +0,0 @@
1
- import itertools
2
- from .base import *
3
- 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 _expand(equation):
45
- """Iterative version of _expand without recursion."""
46
- # Stack: (node, child_index, partially_processed_children)
47
- stack = [(equation, 0, [])]
48
-
49
- while stack:
50
- node, child_index, processed_children = stack.pop()
51
-
52
- # If all children are processed
53
- if child_index >= len(node.children):
54
- # Replace children with processed versions
55
- node.children = processed_children
56
-
57
- # === Handle f_pow ===
58
- if node.name == "f_pow":
59
- n = frac(node.children[1])
60
- if n is not None and n.denominator == 1 and n.numerator > 1:
61
- # Convert power to repeated multiplication
62
- power_children = [node.children[0] for _ in range(n.numerator)]
63
- new_node = TreeNode("f_mul", power_children)
64
- # Flatten tree
65
- node = flatten_tree(new_node)
66
- # Push it back for further processing
67
- stack.append((node, 0, []))
68
- continue
69
-
70
- # === Handle f_mul ===
71
- elif node.name == "f_mul":
72
- # Separate lone children and bracket children
73
- lone_children = tree_form("d_1")
74
- bracket_children = []
75
-
76
- # Iterate in reverse (like original)
77
- for child in reversed(node.children):
78
- if child.name == "f_add":
79
- bracket_children.append(child)
80
- elif child.name == "f_pow" and child.children[0].name == "f_add":
81
- n = frac(child.children[1])
82
- if n is not None and n.denominator == 1 and n.numerator > 1:
83
- for _ in range(n.numerator):
84
- bracket_children.append(child.children[0])
85
- else:
86
- lone_children = lone_children * child
87
- else:
88
- lone_children = lone_children * child
89
-
90
- lone_children = simplify(lone_children)
91
-
92
- # Distribute bracket children over lone children iteratively
93
- while bracket_children:
94
- tmp = tree_form("d_0")
95
- bracket = bracket_children.pop(0)
96
- for bc in bracket.children:
97
- if lone_children.name == "f_add":
98
- for lc in lone_children.children:
99
- tmp = tmp + bc * lc
100
- else:
101
- tmp = tmp + bc * lone_children
102
- # Simplify after each distribution
103
- lone_children = flatten_tree(simplify(tmp))
104
-
105
- node = lone_children
106
-
107
- # === Return node to parent ===
108
- if stack:
109
- parent, idx, parent_children = stack.pop()
110
- parent_children.append(node)
111
- stack.append((parent, idx + 1, parent_children))
112
- else:
113
- # Root node fully expanded
114
- return node
115
-
116
- else:
117
- # Push current node back for next child
118
- stack.append((node, child_index, processed_children))
119
- # Push the child to process next
120
- child = flatten_tree(node.children[child_index])
121
- stack.append((child, 0, []))
122
-
123
- def expand(eq):
124
- return _expand(eq)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes