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/matrix.py ADDED
@@ -0,0 +1,228 @@
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
+ if left == tree_form("d_1"):
74
+ return right
75
+ if right == tree_form("d_1"):
76
+ return left
77
+ left2, right2 = left, right
78
+ if left2.name != "f_pow":
79
+ left2 = left2 ** 1
80
+ if right2.name != "f_pow":
81
+ right2 = right2 ** 1
82
+ if left2.name == "f_pow" and right2.name == "f_pow" and left2.children[0]==right2.children[0]:
83
+ return simplify(left2.children[0]**(left2.children[1]+right2.children[1]))
84
+ A,B = promote(left), promote(right)
85
+
86
+ # vector · vector
87
+ if is_vector(A) and is_vector(B):
88
+ return dot(A,B)
89
+ # matrix × matrix
90
+ if is_matrix(A) and is_matrix(B):
91
+ return py_to_tree(matmul(A,B))
92
+ # scalar × vector
93
+ for _ in range(2):
94
+ if contains_neg(A) and is_vector(B):
95
+ return py_to_tree([TreeNode("f_mul",[A,x]) for x in B])
96
+ # scalar × matrix
97
+ if contains_neg(A) and is_matrix(B):
98
+ return py_to_tree([[TreeNode("f_mul",[A,x]) for x in row] for row in B])
99
+ A, B = B, A
100
+ return None
101
+ def add_vec(A, B):
102
+ if len(A) != len(B):
103
+ raise ValueError("Vector dimension mismatch")
104
+
105
+ return [
106
+ TreeNode("f_add", [A[i], B[i]])
107
+ for i in range(len(A))
108
+ ]
109
+ def matadd(A, B):
110
+ if len(A) != len(B) or len(A[0]) != len(B[0]):
111
+ raise ValueError("Matrix dimension mismatch")
112
+
113
+ n = len(A)
114
+ m = len(A[0])
115
+
116
+ return [
117
+ [
118
+ TreeNode("f_add", [A[i][j], B[i][j]])
119
+ for j in range(m)
120
+ ]
121
+ for i in range(n)
122
+ ]
123
+ def addition(left,right):
124
+ A,B = promote(left), promote(right)
125
+ # vector + vector
126
+ if is_vector(A) and is_vector(B):
127
+ return add_vec(A,B)
128
+ # matrix + matrix
129
+ if is_matrix(A) and is_matrix(B):
130
+ return py_to_tree(matadd(A,B))
131
+ return None
132
+ '''
133
+ def fold_wmul(eq):
134
+ if eq.name == "f_pow" and eq.children[1].name.startswith("d_"):
135
+ n = int(eq.children[1].name[2:])
136
+ if n == 1:
137
+ eq = eq.children[0]
138
+ elif n > 1:
139
+ tmp = promote(eq.children[0])
140
+ if is_matrix(tmp):
141
+ orig =tmp
142
+ for i in range(n-1):
143
+ tmp = matmul(orig, tmp)
144
+ eq = py_to_tree(tmp)
145
+ elif eq.name in ["f_wmul", "f_add"]:
146
+ if len(eq.children) == 1:
147
+ eq = eq.children[0]
148
+ else:
149
+ i = len(eq.children)-1
150
+ while i>0:
151
+ if eq.name == "f_wmul":
152
+ out = multiply(eq.children[i-1], eq.children[i])
153
+ else:
154
+ out = addition(eq.children[i-1], eq.children[i])
155
+ if out is not None:
156
+ eq.children.pop(i)
157
+ eq.children.pop(i-1)
158
+ eq.children.insert(i-1,out)
159
+ i = i-1
160
+ return TreeNode(eq.name, [fold_wmul(child) for child in eq.children])
161
+ '''
162
+ def fold_wmul(root):
163
+ # Post-order traversal using explicit stack
164
+ stack = [(root, False)]
165
+ newnode = {}
166
+
167
+ while stack:
168
+ node, visited = stack.pop()
169
+
170
+ if not visited:
171
+ # First time: push back as visited, then children
172
+ stack.append((node, True))
173
+ for child in node.children:
174
+ stack.append((child, False))
175
+ else:
176
+ # All children already processed
177
+ children = [newnode[c] for c in node.children]
178
+ eq = TreeNode(node.name, children)
179
+
180
+ # ---- original rewrite logic ----
181
+
182
+ if eq.name == "f_pow" and eq.children[1].name.startswith("d_"):
183
+ n = int(eq.children[1].name[2:])
184
+ if n == 1:
185
+ eq = eq.children[0]
186
+ elif n > 1:
187
+ tmp = promote(eq.children[0])
188
+ if is_matrix(tmp):
189
+ orig = tmp
190
+ for _ in range(n - 1):
191
+ tmp = matmul(orig, tmp)
192
+ eq = py_to_tree(tmp)
193
+
194
+ elif eq.name in ["f_wmul", "f_add"]:
195
+ if len(eq.children) == 1:
196
+ eq = eq.children[0]
197
+ else:
198
+ i = len(eq.children) - 1
199
+ while i > 0:
200
+ if eq.name == "f_wmul":
201
+ out = multiply(eq.children[i - 1], eq.children[i])
202
+ else:
203
+ out = addition(eq.children[i - 1], eq.children[i])
204
+
205
+ if out is not None:
206
+ eq.children.pop(i)
207
+ eq.children.pop(i - 1)
208
+ eq.children.insert(i - 1, out)
209
+ i -= 1
210
+
211
+ # --------------------------------
212
+
213
+ newnode[node] = eq
214
+
215
+ return newnode[root]
216
+
217
+ def flat(eq):
218
+ return flatten_tree(eq, ["f_wmul"])
219
+ def use(eq):
220
+ return TreeNode(eq.name, [use(child) for child in eq.children])
221
+ def _matrix_solve(eq):
222
+ if TreeNode.matmul == True:
223
+ TreeNode.matmul = False
224
+ eq = dowhile(eq, lambda x: fold_wmul(use(flat(x))))
225
+ TreeNode.matmul = True
226
+ return eq
227
+ def matrix_solve(eq):
228
+ return _matrix_solve(eq)
mathai/ode.py ADDED
@@ -0,0 +1,124 @@
1
+ from .factor import factor
2
+ from .expand import expand
3
+ from .base import *
4
+ from .fraction import fraction
5
+ from .simplify import simplify
6
+ import copy
7
+
8
+ def inversediff(lhs, rhs):
9
+ count = 4
10
+ while contain(rhs, tree_form("v_1")) or contain(lhs, tree_form("v_0")):
11
+ success = False
12
+ if rhs.name == "f_add":
13
+ for i in range(len(rhs.children)-1,-1,-1):
14
+ if not contain(rhs.children[i], tree_form("v_0")) or str_form(tree_form("v_1").fx("dif")) in [str_form(x) for x in factor_generation(rhs.children[i])]:
15
+ if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
16
+ success = True
17
+ lhs = lhs - rhs.children[i]
18
+ rhs.children.pop(i)
19
+ elif rhs.name == "f_mul":
20
+ for i in range(len(rhs.children)-1,-1,-1):
21
+ if not contain(rhs.children[i], tree_form("v_0")):
22
+ if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
23
+ success = True
24
+ lhs = lhs / rhs.children[i]
25
+ rhs.children.pop(i)
26
+ if len(rhs.children) == 1:
27
+ rhs = rhs.children[0]
28
+ rhs, lhs = copy.deepcopy([simplify(lhs), simplify(rhs)])
29
+ if rhs.name == "f_add":
30
+ for i in range(len(rhs.children)-1,-1,-1):
31
+ if not contain(rhs.children[i], tree_form("v_1")) or str_form(tree_form("v_0").fx("dif")) in [str_form(x) for x in factor_generation(rhs.children[i])]:
32
+ if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
33
+ success = True
34
+ lhs = lhs - rhs.children[i]
35
+ rhs.children.pop(i)
36
+ elif rhs.name == "f_mul":
37
+ for i in range(len(rhs.children)-1,-1,-1):
38
+ if not contain(rhs.children[i], tree_form("v_1")):
39
+ if contain(rhs.children[i], tree_form("v_0")) or contain(rhs.children[i], tree_form("v_1")):
40
+ success = True
41
+ lhs = lhs / rhs.children[i]
42
+ rhs.children.pop(i)
43
+ rhs, lhs = copy.deepcopy([simplify(lhs), simplify(rhs)])
44
+ if not success:
45
+ lhs, rhs = factor(lhs),factor(rhs)
46
+ count -= 1
47
+ if count == 0:
48
+ return simplify(e0(lhs-rhs))
49
+ return simplify(e0(lhs-rhs))
50
+
51
+ intconst = ["v_"+str(i) for i in range(101,150)]
52
+ def allocvar():
53
+ global intconst
54
+ return tree_form(intconst.pop(0))
55
+
56
+ def epowersplit(eq):
57
+ if eq.name == "f_pow" and eq.children[1].name == "f_add":
58
+ return product([eq.children[0]**child for child in eq.children[1].children])
59
+ return TreeNode(eq.name, [epowersplit(child) for child in eq.children])
60
+ def esolve(s):
61
+ if s.name == "f_add" and "f_log" in str_form(s):
62
+ return product([tree_form("s_e")**child for child in s.children]) - tree_form("d_1")
63
+ return TreeNode(s.name, [esolve(child) for child in s.children])
64
+ def diffsolve_sep2(eq):
65
+ global tab
66
+
67
+ s = []
68
+ eq = simplify(expand(eq))
69
+ eq = e1(eq)
70
+
71
+ def vlor1(eq):
72
+ if contain(eq, tree_form("v_0")) and not contain(eq, tree_form("v_1")):
73
+ return True
74
+ if contain(eq, tree_form("v_1")) and not contain(eq, tree_form("v_0")):
75
+ return True
76
+ return False
77
+ if eq.name == "f_add" and all(vlor1(child) and [str_form(x) for x in factor_generation(copy.deepcopy(child))].count(str_form(tree_form(vlist(child)[0]).fx("dif")))==1 for child in eq.children):
78
+ for child in eq.children:
79
+ v = vlist(child)[0]
80
+ v2 = tree_form(v).fx("dif")
81
+ child = replace(child, v2, tree_form("d_1"))
82
+ child = simplify(child)
83
+
84
+
85
+ tmp6 = TreeNode("f_integrate", [child, tree_form(v)])
86
+ s.append(tmp6)
87
+
88
+ if s[-1] is None:
89
+ return None
90
+ s.append(allocvar())
91
+ else:
92
+ return None
93
+ s = summation(s)
94
+ s = simplify(e0(s))
95
+
96
+ return groupe(s)
97
+ def e0(eq):
98
+ return TreeNode("f_eq", [eq, tree_form("d_0")])
99
+ def e1(eq):
100
+ if eq.name == "f_eq":
101
+ eq = eq.children[0]
102
+ return eq
103
+ def groupe(eq):
104
+ eq = esolve(eq)
105
+ eq = simplify(eq)
106
+ eq = fraction(eq)
107
+ eq = simplify(eq)
108
+ eq = epowersplit(eq)
109
+ return eq
110
+
111
+ def diffsolve_sep(eq):
112
+ eq = epowersplit(eq)
113
+
114
+ eq = inversediff(tree_form("d_0"), eq.children[0].copy_tree())
115
+ return eq
116
+
117
+ def diffsolve(eq):
118
+ orig = eq.copy_tree()
119
+
120
+
121
+ eq = diffsolve_sep2(eq)
122
+ if eq is None:
123
+ return orig
124
+ return eq
mathai/parser.py CHANGED
@@ -37,7 +37,7 @@ grammar = """
37
37
  | arithmetic "-" term -> sub
38
38
  | term
39
39
 
40
- ?term: term "*" power -> mul
40
+ ?term: term "*" power -> wmul
41
41
  | term "/" power -> div
42
42
  | term "." power -> dot
43
43
  | power
@@ -59,7 +59,7 @@ grammar = """
59
59
  | ESCAPED_STRING -> string
60
60
  | CAPITAL_ID -> matrix
61
61
 
62
- FUNC_NAME: "midpoint" | "ref" | "subs" | "try" | "forall" | "imply" | "exist" | "len" | "sum" | "angle" | "line" | "sum2" | "charge" | "electricfield" | "perm" | "point" | "equationrhs" | "transpose" | "equationlhs" | "equation" | "error" | "covariance" | "variance" | "expect" | "mag" | "rad" | "laplace" | "diverge" | "pdif" | "gradient" | "curl" | "point1" | "point2" | "dot" | "point3" | "line1" | "line2" | "line3" | "sin" | "circumcenter" | "eqtri" | "linesegment" | "cos" | "tan" | "log" | "sqrt" | "integrate" | "dif" | "abs" | "cosec" | "sec" | "cot" | "arctan" | "arcsin" | "arccos" | "log10"
62
+ FUNC_NAME: "midpoint" | "ref" | "subs" | "try" | "limit" | "forall" | "limitpinf" | "imply" | "exist" | "len" | "sum" | "angle" | "line" | "sum2" | "charge" | "electricfield" | "perm" | "point" | "equationrhs" | "transpose" | "equationlhs" | "equation" | "error" | "covariance" | "variance" | "expect" | "mag" | "rad" | "laplace" | "diverge" | "pdif" | "gradient" | "curl" | "point1" | "point2" | "dot" | "point3" | "line1" | "line2" | "line3" | "sin" | "circumcenter" | "eqtri" | "linesegment" | "cos" | "tan" | "log" | "sqrt" | "integrate" | "dif" | "abs" | "cosec" | "sec" | "cot" | "arctan" | "arcsin" | "arccos" | "log10"
63
63
 
64
64
  VARIABLE: /[a-z]/ | "nabla" | "pi" | "kc" | "hbar" | "em" | "ec" | "anot" | "false" | "true"
65
65
 
@@ -85,7 +85,7 @@ def parse(equation, funclist=None):
85
85
 
86
86
  parser_main = Lark(grammar2, start='start', parser='lalr')
87
87
  parse_tree = parser_main.parse(equation)
88
-
88
+
89
89
  # Convert Lark tree to TreeNode
90
90
  def convert_to_treenode(parse_tree):
91
91
  if isinstance(parse_tree, Tree):
@@ -130,7 +130,7 @@ def parse(equation, funclist=None):
130
130
  if tree_node.name == "pass_through":
131
131
  return fxchange(tree_node.children[0])
132
132
  return TreeNode(
133
- "f_" + tree_node.name if tree_node.name in tmp3 + ["try", "ref", "sqrt","imply","forall","exist","exclude","union","intersection","len","index","angle","charge","sum2","electricfield","line","point","sum","transpose","equationrhs","equationlhs","equation","covariance","variance","expect","error","laplace","dot","curl","pdif","diverge","gradient","rad","ge","le","gt","lt","eqtri","linesegment","midpoint","mag","point1","point2","point3","line1","line2","line3","log10","arcsin","arccos","arctan","list","cosec","sec","cot","equiv","or","not","and","circumcenter","eq","sub","add","sin","cos","tan","mul","integrate","dif","pow","div","log","abs"] else "d_" + tree_node.name,
133
+ "f_" + tree_node.name if tree_node.name in tmp3 + ["limitpinf", "limit", "try", "ref", "sqrt","imply","forall","exist","exclude","union","intersection","len","index","angle","charge","sum2","electricfield","line","point","sum","transpose","equationrhs","equationlhs","equation","covariance","variance","expect","error","laplace","dot","curl","pdif","diverge","gradient","rad","ge","le","gt","lt","eqtri","linesegment","midpoint","mag","point1","point2","point3","line1","line2","line3","log10","arcsin","arccos","arctan","list","cosec","sec","cot","equiv","or","not","and","circumcenter","eq","sub","add","sin","cos","tan","wmul","integrate","dif","pow","div","log","abs"] else "d_" + tree_node.name,
134
134
  [fxchange(child) for child in tree_node.children]
135
135
  )
136
136
 
@@ -146,13 +146,19 @@ def parse(equation, funclist=None):
146
146
  for i, c in enumerate([chr(x+ord("A")) for x in range(0,26)]):
147
147
  tree_node = replace(tree_node, tree_form("d_"+c), tree_form("v_-"+str(i+1)))
148
148
  tree_node = replace(tree_node, tree_form("f_"+c), tree_form("v_-"+str(i+1)))
149
-
150
- # Final recursive replacements
149
+
151
150
  def rfx(tree_node):
152
151
  if tree_node.name[:3] == "d_c":
153
152
  return tree_form("v_" + str(int(tree_node.name[3:])+100))
154
153
  tree_node.children = [rfx(child) for child in tree_node.children]
155
154
  return tree_node
156
-
155
+
157
156
  tree_node = rfx(tree_node)
157
+ tree_node = flatten_tree(tree_node, ["f_wmul"])
158
+ if TreeNode.matmul == True:
159
+ TreeNode.matmul = False
160
+ tree_node = use(tree_form(str_form(tree_node).replace("f_w","f_")))
161
+ TreeNode.matmul = True
162
+ else:
163
+ tree_node = tree_form(str_form(tree_node).replace("f_w","f_"))
158
164
  return tree_node
mathai/parsetab.py ADDED
@@ -0,0 +1,61 @@
1
+
2
+ # parsetab.py
3
+ # This file is automatically generated. Do not edit.
4
+ # pylint: disable=W,C,R
5
+ _tabversion = '3.10'
6
+
7
+ _lr_method = 'LALR'
8
+
9
+ _lr_signature = 'leftEQUIVleftIMPLYleftORleftANDleftEQLTGTLEGEleftPLUSMINUSleftTIMESDIVDOTrightPOWrightNOTUMINUSUPLUSAND CAPITAL_ID CNUMBER COMMA DIV DOT EQ EQUIV GE GT IMPLY LBRACK LE LPAREN LT MINUS NOT NUMBER OR PLUS POW RBRACK RPAREN STRING TIMES VARIABLEstart : exprexpr : expr EQUIV exprexpr : expr IMPLY exprexpr : expr OR exprexpr : expr AND exprexpr : NOT exprexpr : expr EQ expr\n | expr LT expr\n | expr GT expr\n | expr LE expr\n | expr GE exprexpr : expr PLUS expr\n | expr MINUS exprexpr : expr TIMES expr\n | expr DIV expr\n | expr DOT exprexpr : expr POW exprexpr : MINUS expr %prec UMINUSexpr : PLUS expr %prec UPLUSexpr : atomexpr : LPAREN expr RPARENexpr : LBRACK expr_list RBRACKexpr : LBRACK RBRACKexpr_list : expr_list COMMA exprexpr_list : exprexpr : VARIABLE LPAREN expr_list RPARENatom : VARIABLE\n | CAPITAL_ID\n | NUMBER\n | CNUMBER\n | STRING'
10
+
11
+ _lr_action_items = {'NOT':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,]),'MINUS':([0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,56,57,],[5,24,5,5,5,-20,5,5,-27,-28,-29,-30,-31,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,-6,-19,-18,24,-23,24,5,24,24,24,24,24,24,24,24,24,-12,-13,-14,-15,-16,-17,-21,-22,5,24,-26,]),'PLUS':([0,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,56,57,],[4,23,4,4,4,-20,4,4,-27,-28,-29,-30,-31,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,-6,-19,-18,23,-23,23,4,23,23,23,23,23,23,23,23,23,-12,-13,-14,-15,-16,-17,-21,-22,4,23,-26,]),'LPAREN':([0,3,4,5,7,8,9,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[7,7,7,7,7,7,36,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'LBRACK':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,]),'VARIABLE':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,]),'CAPITAL_ID':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,]),'NUMBER':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,]),'CNUMBER':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,]),'STRING':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,]),'$end':([1,2,6,9,10,11,12,13,29,30,31,34,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,57,],[0,-1,-20,-27,-28,-29,-30,-31,-6,-19,-18,-23,-2,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,-26,]),'EQUIV':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[14,-20,-27,-28,-29,-30,-31,-6,-19,-18,14,-23,14,-2,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,14,-26,]),'IMPLY':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[15,-20,-27,-28,-29,-30,-31,-6,-19,-18,15,-23,15,15,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,15,-26,]),'OR':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[16,-20,-27,-28,-29,-30,-31,-6,-19,-18,16,-23,16,16,16,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,16,-26,]),'AND':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[17,-20,-27,-28,-29,-30,-31,-6,-19,-18,17,-23,17,17,17,17,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,17,-26,]),'EQ':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[18,-20,-27,-28,-29,-30,-31,-6,-19,-18,18,-23,18,18,18,18,18,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,18,-26,]),'LT':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[19,-20,-27,-28,-29,-30,-31,-6,-19,-18,19,-23,19,19,19,19,19,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,19,-26,]),'GT':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[20,-20,-27,-28,-29,-30,-31,-6,-19,-18,20,-23,20,20,20,20,20,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,20,-26,]),'LE':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[21,-20,-27,-28,-29,-30,-31,-6,-19,-18,21,-23,21,21,21,21,21,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,21,-26,]),'GE':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[22,-20,-27,-28,-29,-30,-31,-6,-19,-18,22,-23,22,22,22,22,22,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,22,-26,]),'TIMES':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[25,-20,-27,-28,-29,-30,-31,-6,-19,-18,25,-23,25,25,25,25,25,25,25,25,25,25,25,25,-14,-15,-16,-17,-21,-22,25,-26,]),'DIV':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[26,-20,-27,-28,-29,-30,-31,-6,-19,-18,26,-23,26,26,26,26,26,26,26,26,26,26,26,26,-14,-15,-16,-17,-21,-22,26,-26,]),'DOT':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[27,-20,-27,-28,-29,-30,-31,-6,-19,-18,27,-23,27,27,27,27,27,27,27,27,27,27,27,27,-14,-15,-16,-17,-21,-22,27,-26,]),'POW':([2,6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[28,-20,-27,-28,-29,-30,-31,-6,-19,-18,28,-23,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,-21,-22,28,-26,]),'RPAREN':([6,9,10,11,12,13,29,30,31,32,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,56,57,],[-20,-27,-28,-29,-30,-31,-6,-19,-18,52,-23,-25,-2,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,57,-24,-26,]),'RBRACK':([6,8,9,10,11,12,13,29,30,31,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,57,],[-20,34,-27,-28,-29,-30,-31,-6,-19,-18,53,-23,-25,-2,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,-24,-26,]),'COMMA':([6,9,10,11,12,13,29,30,31,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,55,56,57,],[-20,-27,-28,-29,-30,-31,-6,-19,-18,54,-23,-25,-2,-3,-4,-5,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-21,-22,54,-24,-26,]),}
12
+
13
+ _lr_action = {}
14
+ for _k, _v in _lr_action_items.items():
15
+ for _x,_y in zip(_v[0],_v[1]):
16
+ if not _x in _lr_action: _lr_action[_x] = {}
17
+ _lr_action[_x][_k] = _y
18
+ del _lr_action_items
19
+
20
+ _lr_goto_items = {'start':([0,],[1,]),'expr':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[2,29,30,31,32,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,35,56,]),'atom':([0,3,4,5,7,8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,36,54,],[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,]),'expr_list':([8,36,],[33,55,]),}
21
+
22
+ _lr_goto = {}
23
+ for _k, _v in _lr_goto_items.items():
24
+ for _x, _y in zip(_v[0], _v[1]):
25
+ if not _x in _lr_goto: _lr_goto[_x] = {}
26
+ _lr_goto[_x][_k] = _y
27
+ del _lr_goto_items
28
+ _lr_productions = [
29
+ ("S' -> start","S'",1,None,None,None),
30
+ ('start -> expr','start',1,'p_start','parser.py',98),
31
+ ('expr -> expr EQUIV expr','expr',3,'p_expr_equiv','parser.py',105),
32
+ ('expr -> expr IMPLY expr','expr',3,'p_expr_imply','parser.py',109),
33
+ ('expr -> expr OR expr','expr',3,'p_expr_or','parser.py',113),
34
+ ('expr -> expr AND expr','expr',3,'p_expr_and','parser.py',117),
35
+ ('expr -> NOT expr','expr',2,'p_expr_not','parser.py',121),
36
+ ('expr -> expr EQ expr','expr',3,'p_expr_cmp','parser.py',128),
37
+ ('expr -> expr LT expr','expr',3,'p_expr_cmp','parser.py',129),
38
+ ('expr -> expr GT expr','expr',3,'p_expr_cmp','parser.py',130),
39
+ ('expr -> expr LE expr','expr',3,'p_expr_cmp','parser.py',131),
40
+ ('expr -> expr GE expr','expr',3,'p_expr_cmp','parser.py',132),
41
+ ('expr -> expr PLUS expr','expr',3,'p_expr_add','parser.py',146),
42
+ ('expr -> expr MINUS expr','expr',3,'p_expr_add','parser.py',147),
43
+ ('expr -> expr TIMES expr','expr',3,'p_expr_mul','parser.py',154),
44
+ ('expr -> expr DIV expr','expr',3,'p_expr_mul','parser.py',155),
45
+ ('expr -> expr DOT expr','expr',3,'p_expr_mul','parser.py',156),
46
+ ('expr -> expr POW expr','expr',3,'p_expr_pow','parser.py',165),
47
+ ('expr -> MINUS expr','expr',2,'p_expr_uminus','parser.py',172),
48
+ ('expr -> PLUS expr','expr',2,'p_expr_uplus','parser.py',176),
49
+ ('expr -> atom','expr',1,'p_expr_atom','parser.py',183),
50
+ ('expr -> LPAREN expr RPAREN','expr',3,'p_expr_paren','parser.py',187),
51
+ ('expr -> LBRACK expr_list RBRACK','expr',3,'p_expr_list','parser.py',191),
52
+ ('expr -> LBRACK RBRACK','expr',2,'p_expr_list_single','parser.py',195),
53
+ ('expr_list -> expr_list COMMA expr','expr_list',3,'p_expr_list_list','parser.py',199),
54
+ ('expr_list -> expr','expr_list',1,'p_expr_list_item','parser.py',203),
55
+ ('expr -> VARIABLE LPAREN expr_list RPAREN','expr',4,'p_expr_func','parser.py',207),
56
+ ('atom -> VARIABLE','atom',1,'p_atom_var','parser.py',214),
57
+ ('atom -> CAPITAL_ID','atom',1,'p_atom_var','parser.py',215),
58
+ ('atom -> NUMBER','atom',1,'p_atom_var','parser.py',216),
59
+ ('atom -> CNUMBER','atom',1,'p_atom_var','parser.py',217),
60
+ ('atom -> STRING','atom',1,'p_atom_var','parser.py',218),
61
+ ]
mathai/printeq.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from .base import *
2
- from .simplify import solve
2
+ from .factor import merge_sqrt
3
+ from .simplify import simplify
3
4
  import copy
4
5
  from fractions import Fraction
5
6
  def abstractexpr(eq):
@@ -11,24 +12,26 @@ def abstractexpr(eq):
11
12
 
12
13
  lst = factor_generation(eq)
13
14
  deno = [item.children[0]**int(item.children[1].name[3:]) for item in lst if item.name == "f_pow" and item.children[1].name[:3] == "d_-"]
14
- if eq.name == "f_mul" and any(item.name[:2] == "d_" and int(item.name[2:]) < 0 for item in lst):
15
- return solve(-eq).fx("neg")
15
+ if eq.name == "f_mul" and any(frac(item) is not None and frac(item) < 0 for item in lst):
16
+ return simplify(-eq, False).fx("neg")
16
17
  if deno != []:
17
18
 
18
19
  num = [item for item in lst if item.name != "f_pow" or item.children[1].name[:3] != "d_-"]
19
20
  if num == []:
20
21
  num = [tree_form("d_1")]
21
- return TreeNode("f_div", [solve(product(num)), solve(product(deno))])
22
+ return TreeNode("f_div", [simplify(product(num), False), simplify(product(deno), False)])
22
23
 
23
24
 
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