mathai 0.6.3__tar.gz → 0.6.5__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.3 → mathai-0.6.5}/PKG-INFO +1 -1
  2. {mathai-0.6.3 → mathai-0.6.5}/mathai/base.py +22 -17
  3. mathai-0.6.5/mathai/matrix.py +224 -0
  4. {mathai-0.6.3 → mathai-0.6.5}/mathai/parser.py +2 -0
  5. {mathai-0.6.3 → mathai-0.6.5}/mathai/simplify.py +0 -1
  6. {mathai-0.6.3 → mathai-0.6.5}/mathai.egg-info/PKG-INFO +1 -1
  7. {mathai-0.6.3 → mathai-0.6.5}/setup.py +1 -1
  8. mathai-0.6.3/mathai/matrix.py +0 -101
  9. {mathai-0.6.3 → mathai-0.6.5}/README.md +0 -0
  10. {mathai-0.6.3 → mathai-0.6.5}/mathai/__init__.py +0 -0
  11. {mathai-0.6.3 → mathai-0.6.5}/mathai/apart.py +0 -0
  12. {mathai-0.6.3 → mathai-0.6.5}/mathai/bivariate_inequality.py +0 -0
  13. {mathai-0.6.3 → mathai-0.6.5}/mathai/console.py +0 -0
  14. {mathai-0.6.3 → mathai-0.6.5}/mathai/diff.py +0 -0
  15. {mathai-0.6.3 → mathai-0.6.5}/mathai/expand.py +0 -0
  16. {mathai-0.6.3 → mathai-0.6.5}/mathai/factor.py +0 -0
  17. {mathai-0.6.3 → mathai-0.6.5}/mathai/fraction.py +0 -0
  18. {mathai-0.6.3 → mathai-0.6.5}/mathai/integrate.py +0 -0
  19. {mathai-0.6.3 → mathai-0.6.5}/mathai/inverse.py +0 -0
  20. {mathai-0.6.3 → mathai-0.6.5}/mathai/limit.py +0 -0
  21. {mathai-0.6.3 → mathai-0.6.5}/mathai/linear.py +0 -0
  22. {mathai-0.6.3 → mathai-0.6.5}/mathai/logic.py +0 -0
  23. {mathai-0.6.3 → mathai-0.6.5}/mathai/ode.py +0 -0
  24. {mathai-0.6.3 → mathai-0.6.5}/mathai/parsetab.py +0 -0
  25. {mathai-0.6.3 → mathai-0.6.5}/mathai/printeq.py +0 -0
  26. {mathai-0.6.3 → mathai-0.6.5}/mathai/structure.py +0 -0
  27. {mathai-0.6.3 → mathai-0.6.5}/mathai/tool.py +0 -0
  28. {mathai-0.6.3 → mathai-0.6.5}/mathai/trig.py +0 -0
  29. {mathai-0.6.3 → mathai-0.6.5}/mathai/univariate_inequality.py +0 -0
  30. {mathai-0.6.3 → mathai-0.6.5}/mathai.egg-info/SOURCES.txt +0 -0
  31. {mathai-0.6.3 → mathai-0.6.5}/mathai.egg-info/dependency_links.txt +0 -0
  32. {mathai-0.6.3 → mathai-0.6.5}/mathai.egg-info/requires.txt +0 -0
  33. {mathai-0.6.3 → mathai-0.6.5}/mathai.egg-info/top_level.txt +0 -0
  34. {mathai-0.6.3 → mathai-0.6.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 0.6.3
3
+ Version: 0.6.5
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,11 +1,12 @@
1
1
  import copy
2
2
  from fractions import Fraction
3
3
  def contains_list_or_neg(node):
4
- if node.name == "f_list" or node.name.startswith("v_-"):
5
- return True
6
- for child in node.children:
7
- if contains_list_or_neg(child):
4
+ stack = [node]
5
+ while stack:
6
+ n = stack.pop()
7
+ if n.name == "f_list" or n.name.startswith("v_-"):
8
8
  return True
9
+ stack.extend(n.children)
9
10
  return False
10
11
  class TreeNode:
11
12
  matmul = None
@@ -30,28 +31,32 @@ class TreeNode:
30
31
  sortable.append(c)
31
32
  else:
32
33
  fixed.append(c)
34
+
35
+ if len(sortable) > 1:
36
+ sortable = TreeNode("f_dmul", list(sorted(sortable, key=lambda x: str_form(x))))
37
+ sortable.name = "f_mul"
38
+
39
+ elif len(sortable) == 1:
40
+ sortable = sortable[0]
41
+
42
+ if isinstance(sortable, TreeNode):
43
+ fixed.append(sortable)
33
44
  if len(fixed) > 1:
34
- fixed = TreeNode("f_wmul", fixed)
45
+ self.name = "f_wmul"
35
46
  elif len(fixed) == 1:
36
- fixed = fixed[0]
37
- if isinstance(fixed, TreeNode):
38
- sortable.append(fixed)
39
- if len(sortable)==1 and name == "f_mul":
40
- self.name = sortable[0].name
41
- if self.name in ["f_add", "f_mul"]:
42
- self.children = list(sorted(sortable[0].children, key=lambda x: str_form(x)))
43
- else:
44
- self.children = sortable[0].children
47
+ self.name = fixed[0].name
48
+ fixed = fixed[0].children
45
49
 
46
- else:
47
- self.children = list(sorted(sortable, key=lambda x: str_form(x)))
50
+
51
+ self.children = fixed
48
52
  else:
49
53
  self.children = children
50
54
 
51
55
 
52
56
  def fx(self, fxname):
53
57
  return TreeNode("f_" + fxname, [self])
54
-
58
+ def copy_tree(self):
59
+ return copy.deepcopy(self)
55
60
  def __repr__(self):
56
61
  return string_equation(str_form(self))
57
62
 
@@ -0,0 +1,224 @@
1
+ from .base import *
2
+ import copy
3
+ from .simplify import simplify
4
+ import itertools
5
+
6
+ # ---------- tree <-> python list ----------
7
+ def tree_to_py(node):
8
+ if node.name=="f_list":
9
+ return [tree_to_py(c) for c in node.children]
10
+ return node
11
+
12
+ def py_to_tree(obj):
13
+ if isinstance(obj,list):
14
+ return TreeNode("f_list",[py_to_tree(x) for x in obj])
15
+ return obj
16
+
17
+ # ---------- shape detection ----------
18
+ def is_vector(x):
19
+ return isinstance(x,list) and all(isinstance(item,TreeNode) for item in x)
20
+ def is_mat(x):
21
+ return isinstance(x,list) and all(isinstance(item,list) for item in x)
22
+ def is_matrix(x):
23
+ return isinstance(x, list) and all(isinstance(item, list) and (is_mat(item) or is_vector(item)) for item in x)
24
+
25
+
26
+ # ---------- algebra primitives ----------
27
+ def dot(u,v):
28
+ if len(u)!=len(v):
29
+ raise ValueError("Vector size mismatch")
30
+ s = tree_form("d_0")
31
+ for a,b in zip(u,v):
32
+ s = TreeNode("f_add",[s,TreeNode("f_mul",[a,b])])
33
+ return s
34
+
35
+ def matmul(A, B):
36
+ # A: n × m
37
+ # B: m × p
38
+
39
+ n = len(A)
40
+ m = len(A[0])
41
+ p = len(B[0])
42
+
43
+ if m != len(B):
44
+ raise ValueError("Matrix dimension mismatch")
45
+
46
+ C = [[tree_form("d_0") for _ in range(p)] for _ in range(n)]
47
+
48
+ for i in range(n):
49
+ for j in range(p):
50
+ for k in range(m):
51
+ C[i][j] = TreeNode(
52
+ "f_add",
53
+ [C[i][j], TreeNode("f_mul", [A[i][k], B[k][j]])]
54
+ )
55
+ return C
56
+
57
+ # ---------- promotion ----------
58
+ def promote(node):
59
+ if node.name=="f_list":
60
+ return tree_to_py(node)
61
+ return node
62
+ def contains_neg(node):
63
+ if isinstance(node, list):
64
+ return False
65
+ if node.name.startswith("v_-"):
66
+ return False
67
+ for child in node.children:
68
+ if not contains_neg(child):
69
+ return False
70
+ return True
71
+ # ---------- multiplication (fully simplified) ----------
72
+ def multiply(left,right):
73
+ left2, right2 = left, right
74
+ if left2.name != "f_pow":
75
+ left2 = left2 ** 1
76
+ if right2.name != "f_pow":
77
+ right2 = right2 ** 1
78
+ if left2.name == "f_pow" and right2.name == "f_pow" and left2.children[0]==right2.children[0]:
79
+ return simplify(left2.children[0]**(left2.children[1]+right2.children[1]))
80
+ A,B = promote(left), promote(right)
81
+
82
+ # vector · vector
83
+ if is_vector(A) and is_vector(B):
84
+ return dot(A,B)
85
+ # matrix × matrix
86
+ if is_matrix(A) and is_matrix(B):
87
+ return py_to_tree(matmul(A,B))
88
+ # scalar × vector
89
+ for _ in range(2):
90
+ if contains_neg(A) and is_vector(B):
91
+ return py_to_tree([TreeNode("f_mul",[A,x]) for x in B])
92
+ # scalar × matrix
93
+ if contains_neg(A) and is_matrix(B):
94
+ return py_to_tree([[TreeNode("f_mul",[A,x]) for x in row] for row in B])
95
+ A, B = B, A
96
+ return None
97
+ def add_vec(A, B):
98
+ if len(A) != len(B):
99
+ raise ValueError("Vector dimension mismatch")
100
+
101
+ return [
102
+ TreeNode("f_add", [A[i], B[i]])
103
+ for i in range(len(A))
104
+ ]
105
+ def matadd(A, B):
106
+ if len(A) != len(B) or len(A[0]) != len(B[0]):
107
+ raise ValueError("Matrix dimension mismatch")
108
+
109
+ n = len(A)
110
+ m = len(A[0])
111
+
112
+ return [
113
+ [
114
+ TreeNode("f_add", [A[i][j], B[i][j]])
115
+ for j in range(m)
116
+ ]
117
+ for i in range(n)
118
+ ]
119
+ def addition(left,right):
120
+ A,B = promote(left), promote(right)
121
+ # vector + vector
122
+ if is_vector(A) and is_vector(B):
123
+ return add_vec(A,B)
124
+ # matrix + matrix
125
+ if is_matrix(A) and is_matrix(B):
126
+ return py_to_tree(matadd(A,B))
127
+ return None
128
+ '''
129
+ def fold_wmul(eq):
130
+ if eq.name == "f_pow" and eq.children[1].name.startswith("d_"):
131
+ n = int(eq.children[1].name[2:])
132
+ if n == 1:
133
+ eq = eq.children[0]
134
+ elif n > 1:
135
+ tmp = promote(eq.children[0])
136
+ if is_matrix(tmp):
137
+ orig =tmp
138
+ for i in range(n-1):
139
+ tmp = matmul(orig, tmp)
140
+ eq = py_to_tree(tmp)
141
+ elif eq.name in ["f_wmul", "f_add"]:
142
+ if len(eq.children) == 1:
143
+ eq = eq.children[0]
144
+ else:
145
+ i = len(eq.children)-1
146
+ while i>0:
147
+ if eq.name == "f_wmul":
148
+ out = multiply(eq.children[i-1], eq.children[i])
149
+ else:
150
+ out = addition(eq.children[i-1], eq.children[i])
151
+ if out is not None:
152
+ eq.children.pop(i)
153
+ eq.children.pop(i-1)
154
+ eq.children.insert(i-1,out)
155
+ i = i-1
156
+ return TreeNode(eq.name, [fold_wmul(child) for child in eq.children])
157
+ '''
158
+ def fold_wmul(root):
159
+ # Post-order traversal using explicit stack
160
+ stack = [(root, False)]
161
+ newnode = {}
162
+
163
+ while stack:
164
+ node, visited = stack.pop()
165
+
166
+ if not visited:
167
+ # First time: push back as visited, then children
168
+ stack.append((node, True))
169
+ for child in node.children:
170
+ stack.append((child, False))
171
+ else:
172
+ # All children already processed
173
+ children = [newnode[c] for c in node.children]
174
+ eq = TreeNode(node.name, children)
175
+
176
+ # ---- original rewrite logic ----
177
+
178
+ if eq.name == "f_pow" and eq.children[1].name.startswith("d_"):
179
+ n = int(eq.children[1].name[2:])
180
+ if n == 1:
181
+ eq = eq.children[0]
182
+ elif n > 1:
183
+ tmp = promote(eq.children[0])
184
+ if is_matrix(tmp):
185
+ orig = tmp
186
+ for _ in range(n - 1):
187
+ tmp = matmul(orig, tmp)
188
+ eq = py_to_tree(tmp)
189
+
190
+ elif eq.name in ["f_wmul", "f_add"]:
191
+ if len(eq.children) == 1:
192
+ eq = eq.children[0]
193
+ else:
194
+ i = len(eq.children) - 1
195
+ while i > 0:
196
+ if eq.name == "f_wmul":
197
+ out = multiply(eq.children[i - 1], eq.children[i])
198
+ else:
199
+ out = addition(eq.children[i - 1], eq.children[i])
200
+
201
+ if out is not None:
202
+ eq.children.pop(i)
203
+ eq.children.pop(i - 1)
204
+ eq.children.insert(i - 1, out)
205
+ i -= 1
206
+
207
+ # --------------------------------
208
+
209
+ newnode[node] = eq
210
+
211
+ return newnode[root]
212
+
213
+ def flat(eq):
214
+ return flatten_tree(eq, ["f_wmul"])
215
+ def use(eq):
216
+ return TreeNode(eq.name, [use(child) for child in eq.children])
217
+ def _matrix_solve(eq):
218
+ if TreeNode.matmul == True:
219
+ TreeNode.matmul = False
220
+ eq = flat(dowhile(eq, lambda x: fold_wmul(flat(x))))
221
+ TreeNode.matmul = True
222
+ return eq
223
+ def matrix_solve(eq):
224
+ return _matrix_solve(eq)
@@ -158,4 +158,6 @@ def parse(equation, funclist=None):
158
158
  TreeNode.matmul = False
159
159
  tree_node = tree_form(str_form(tree_node).replace("f_w","f_"))
160
160
  TreeNode.matmul = True
161
+ else:
162
+ tree_node = tree_form(str_form(tree_node).replace("f_w","f_"))
161
163
  return tree_node
@@ -20,7 +20,6 @@ def clear_div(eq, denom):
20
20
  return tree_form("d_0"), True
21
21
  lst3 = []
22
22
  for item in lst:
23
- print(str_form(item))
24
23
  if "v_" not in str_form(item) and compute(item) < 0:
25
24
  lst3.append(item)
26
25
  sign = denom
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 0.6.3
3
+ Version: 0.6.5
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.3",
5
+ version="0.6.5",
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,101 +0,0 @@
1
- from .base import *
2
- import copy
3
- from .simplify import simplify
4
- import itertools
5
-
6
- # ---------- tree <-> python list ----------
7
- def tree_to_py(node):
8
- if node.name=="f_list":
9
- return [tree_to_py(c) for c in node.children]
10
- return node
11
-
12
- def py_to_tree(obj):
13
- if isinstance(obj,list):
14
- return TreeNode("f_list",[py_to_tree(x) for x in obj])
15
- return obj
16
-
17
- # ---------- shape detection ----------
18
- def is_vector(x):
19
- return isinstance(x,list) and all(isinstance(item,TreeNode) for item in x)
20
- def is_mat(x):
21
- return isinstance(x,list) and all(isinstance(item,list) for item in x)
22
- def is_matrix(x):
23
- return isinstance(x, list) and all(isinstance(item, list) and (is_mat(item) or is_vector(item)) for item in x)
24
-
25
-
26
- # ---------- algebra primitives ----------
27
- def dot(u,v):
28
- if len(u)!=len(v):
29
- raise ValueError("Vector size mismatch")
30
- s = tree_form("d_0")
31
- for a,b in zip(u,v):
32
- s = TreeNode("f_add",[s,TreeNode("f_mul",[a,b])])
33
- return s
34
-
35
- def matmul(A,B):
36
- n,m,p = len(A), len(A[0]), len(B[0])
37
- if m!=len(B):
38
- raise ValueError("Matrix dimension mismatch")
39
- z = tree_form("d_0")
40
- C = [[z for _ in range(p)] for _ in range(n)]
41
- for i in range(n):
42
- for j in range(p):
43
- for k in range(m):
44
- C[i][j] = TreeNode("f_add",[C[i][j], TreeNode("f_mul",[A[i][k], B[k][j]])])
45
- return C
46
-
47
- # ---------- promotion ----------
48
- def promote(node):
49
- if node.name=="f_list":
50
- return tree_to_py(node)
51
- return node
52
- def contains_neg(node):
53
- if isinstance(node, list):
54
- return False
55
- if node.name.startswith("v_-"):
56
- return False
57
- for child in node.children:
58
- if not contains_neg(child):
59
- return False
60
- return True
61
- # ---------- multiplication (fully simplified) ----------
62
- def multiply(left,right):
63
- A,B = promote(left), promote(right)
64
-
65
- # vector · vector
66
- if is_vector(A) and is_vector(B):
67
- return dot(A,B)
68
- # matrix × matrix
69
- if is_matrix(A) and is_matrix(B):
70
- return py_to_tree(matmul(A,B))
71
- # scalar × vector
72
- for _ in range(2):
73
- if contains_neg(A) and is_vector(B):
74
- return py_to_tree([TreeNode("f_mul",[A,x]) for x in B])
75
- # scalar × matrix
76
- if contains_neg(A) and is_matrix(B):
77
- return py_to_tree([[TreeNode("f_mul",[A,x]) for x in row] for row in B])
78
- A, B = B, A
79
- return None
80
-
81
- def fold_wmul(eq):
82
- if eq.name=="f_wmul" and any(item.name=="f_list" or item.name.startswith("v_-") for item in eq.children):
83
- i = len(eq.children)-1
84
- while i>0:
85
- out = multiply(eq.children[i], eq.children[i-1])
86
- if out is not None:
87
- eq.children.pop(i)
88
- eq.children.pop(i-1)
89
- eq.children.append(out)
90
- i = i-1
91
- return eq
92
- return TreeNode(eq.name, [fold_wmul(child) for child in eq.children])
93
- def flat(eq):
94
- return flatten_tree(tree_form(str_form(eq).replace("f_w","f_")))
95
- def matrix_solve(eq):
96
- if TreeNode.matmul == True:
97
- TreeNode.matmul = False
98
- eq = simplify(eq)
99
- eq = flat(dowhile(eq, lambda x: fold_wmul(flat(x))))
100
- TreeNode.matmul = True
101
- return 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
File without changes
File without changes
File without changes
File without changes