mathai 0.2.7__py3-none-any.whl → 0.2.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/parser.py CHANGED
@@ -1,154 +1,154 @@
1
- import copy
2
- from lark import Lark, Tree
3
- from .base import *
4
- import re
5
-
6
- grammar = """
7
- ?start: expr
8
-
9
- ?expr: logic_equiv
10
-
11
- ?logic_equiv: logic_imply
12
- | logic_equiv "<->" logic_imply -> equiv
13
-
14
- ?logic_imply: logic_or
15
- | logic_or "->" logic_imply -> imply
16
-
17
- ?logic_or: logic_and
18
- | logic_or "|" logic_and -> or
19
- | logic_or "||" logic_and -> or
20
-
21
- ?logic_and: comparison
22
- | logic_and "&" comparison -> and
23
- | logic_and "&&" comparison -> and
24
-
25
- ?comparison: arithmetic
26
- | comparison "=" arithmetic -> eq
27
- | comparison "<" arithmetic -> lt
28
- | comparison ">" arithmetic -> gt
29
- | comparison "<=" arithmetic -> le
30
- | comparison ">=" arithmetic -> ge
31
-
32
- ?arithmetic: arithmetic "+" term -> add
33
- | arithmetic "-" term -> sub
34
- | term
35
-
36
- ?term: term "*" power -> mul
37
- | term "/" power -> div
38
- | term "." power -> dot
39
- | power
40
-
41
- ?power: power "^" factor -> pow
42
- | power "**" factor -> pow
43
- | factor
44
-
45
- ?factor: "-" factor -> neg
46
- | "+" factor -> pass_through
47
- | atom
48
-
49
- ?atom: NUMBER -> number
50
- | VARIABLE -> variable
51
- | FUNC_NAME "(" [expr ("," expr)*] ")" -> func
52
- | "[" [expr ("," expr)*] "]" -> list
53
- | "(" expr ")" -> paren
54
- | CNUMBER -> cnumber
55
- | ESCAPED_STRING -> string
56
- | CAPITAL_ID -> matrix
57
-
58
- FUNC_NAME: "midpoint" | "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"
59
-
60
- VARIABLE: /[a-z]/ | "nabla" | "pi" | "kc" | "hbar" | "em" | "ec" | "anot" | "false" | "true"
61
-
62
- CAPITAL_ID: /[A-Z]/
63
-
64
- CNUMBER: /c[0-9]+/
65
-
66
- %import common.NUMBER
67
- %import common.ESCAPED_STRING
68
- %import common.WS_INLINE
69
- %ignore WS_INLINE
70
- """
71
-
72
- def parse(equation, funclist=None):
73
- equation = copy.copy(equation.replace(" ", ""))
74
- grammar2 = copy.deepcopy(grammar)
75
- if funclist is not None:
76
- output = grammar2.split("\n")
77
- for i in range(len(output)):
78
- if "FUNC_NAME:" in output[i]:
79
- output[i] = output[i].replace("FUNC_NAME: ", "FUNC_NAME: " + " | ".join(['"' + x + '"' for x in funclist]) + " | ")
80
- grammar2 = "\n".join(output)
81
-
82
- parser_main = Lark(grammar2, start='start', parser='lalr')
83
- parse_tree = parser_main.parse(equation)
84
-
85
- # Convert Lark tree to TreeNode
86
- def convert_to_treenode(parse_tree):
87
- if isinstance(parse_tree, Tree):
88
- node = TreeNode(parse_tree.data)
89
- node.children = [convert_to_treenode(child) for child in parse_tree.children]
90
- return node
91
- else:
92
- return TreeNode(str(parse_tree))
93
-
94
- # Flatten unnecessary nodes like pass_through
95
- def remove_past(equation):
96
- if equation.name in {"number", "paren", "func", "variable", "pass_through", "cnumber", "string", "matrix"}:
97
- if len(equation.children) == 1:
98
- return remove_past(equation.children[0])
99
- else:
100
- equation.children = [remove_past(child) for child in equation.children]
101
- return TreeNode(equation.children[0].name, equation.children[1:])
102
- equation.children = [remove_past(child) for child in equation.children]
103
- return equation
104
-
105
- # Handle indices if any
106
- def prefixindex(equation):
107
- if equation.name == "base" and len(equation.children) > 1:
108
- return TreeNode("index", [equation.children[0]] + equation.children[1].children)
109
- return TreeNode(equation.name, [prefixindex(child) for child in equation.children])
110
-
111
- tree_node = convert_to_treenode(parse_tree)
112
- tree_node = remove_past(tree_node)
113
- tree_node = prefixindex(tree_node)
114
-
115
- # Convert function names and constants
116
- def fxchange(tree_node):
117
- tmp3 = funclist if funclist is not None else []
118
- if tree_node.name == "neg":
119
- child = fxchange(tree_node.children[0])
120
- # if the child is a number, make it negative
121
- if child.name.startswith("d_") and re.match(r"d_\d+(\.\d+)?$", child.name):
122
- return TreeNode("d_" + str(-int(child.name[2:])))
123
- else:
124
- # otherwise subtract from zero
125
- return TreeNode("f_sub", [tree_form("d_0"), child])
126
- if tree_node.name == "pass_through":
127
- return fxchange(tree_node.children[0])
128
- return TreeNode(
129
- "f_" + tree_node.name if tree_node.name in tmp3 + ["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,
130
- [fxchange(child) for child in tree_node.children]
131
- )
132
-
133
- tree_node = fxchange(tree_node)
134
-
135
- # Replace common constants
136
- for const in ["e","pi","kc","em","ec","anot","hbar","false","true","i","nabla"]:
137
- tree_node = replace(tree_node, tree_form("d_"+const), tree_form("s_"+const))
138
-
139
- # Map letters to variables
140
- for i, c in enumerate(["x","y","z"] + [chr(x+ord("a")) for x in range(0,23)]):
141
- tree_node = replace(tree_node, tree_form("d_"+c), tree_form("v_"+str(i)))
142
- for i, c in enumerate([chr(x+ord("A")) for x in range(0,26)]):
143
- tree_node = replace(tree_node, tree_form("d_"+c), tree_form("v_-"+str(i+1)))
144
- tree_node = replace(tree_node, tree_form("f_"+c), tree_form("v_-"+str(i+1)))
145
-
146
- # Final recursive replacements
147
- def rfx(tree_node):
148
- if tree_node.name[:3] == "d_c":
149
- return tree_form("v_" + str(int(tree_node.name[3:])+100))
150
- tree_node.children = [rfx(child) for child in tree_node.children]
151
- return tree_node
152
-
153
- tree_node = rfx(tree_node)
154
- return tree_node
1
+ import copy
2
+ from lark import Lark, Tree
3
+ from .base import *
4
+ import re
5
+
6
+ grammar = """
7
+ ?start: expr
8
+
9
+ ?expr: logic_equiv
10
+
11
+ ?logic_equiv: logic_imply
12
+ | logic_equiv "<->" logic_imply -> equiv
13
+
14
+ ?logic_imply: logic_or
15
+ | logic_or "->" logic_imply -> imply
16
+
17
+ ?logic_or: logic_and
18
+ | logic_or "|" logic_and -> or
19
+ | logic_or "||" logic_and -> or
20
+
21
+ ?logic_and: comparison
22
+ | logic_and "&" comparison -> and
23
+ | logic_and "&&" comparison -> and
24
+
25
+ ?comparison: arithmetic
26
+ | comparison "=" arithmetic -> eq
27
+ | comparison "<" arithmetic -> lt
28
+ | comparison ">" arithmetic -> gt
29
+ | comparison "<=" arithmetic -> le
30
+ | comparison ">=" arithmetic -> ge
31
+
32
+ ?arithmetic: arithmetic "+" term -> add
33
+ | arithmetic "-" term -> sub
34
+ | term
35
+
36
+ ?term: term "*" power -> mul
37
+ | term "/" power -> div
38
+ | term "." power -> dot
39
+ | power
40
+
41
+ ?power: power "^" factor -> pow
42
+ | power "**" factor -> pow
43
+ | factor
44
+
45
+ ?factor: "-" factor -> neg
46
+ | "+" factor -> pass_through
47
+ | atom
48
+
49
+ ?atom: NUMBER -> number
50
+ | VARIABLE -> variable
51
+ | FUNC_NAME "(" [expr ("," expr)*] ")" -> func
52
+ | "[" [expr ("," expr)*] "]" -> list
53
+ | "(" expr ")" -> paren
54
+ | CNUMBER -> cnumber
55
+ | ESCAPED_STRING -> string
56
+ | CAPITAL_ID -> matrix
57
+
58
+ FUNC_NAME: "midpoint" | "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"
59
+
60
+ VARIABLE: /[a-z]/ | "nabla" | "pi" | "kc" | "hbar" | "em" | "ec" | "anot" | "false" | "true"
61
+
62
+ CAPITAL_ID: /[A-Z]/
63
+
64
+ CNUMBER: /c[0-9]+/
65
+
66
+ %import common.NUMBER
67
+ %import common.ESCAPED_STRING
68
+ %import common.WS_INLINE
69
+ %ignore WS_INLINE
70
+ """
71
+
72
+ def parse(equation, funclist=None):
73
+ equation = copy.copy(equation.replace(" ", ""))
74
+ grammar2 = copy.deepcopy(grammar)
75
+ if funclist is not None:
76
+ output = grammar2.split("\n")
77
+ for i in range(len(output)):
78
+ if "FUNC_NAME:" in output[i]:
79
+ output[i] = output[i].replace("FUNC_NAME: ", "FUNC_NAME: " + " | ".join(['"' + x + '"' for x in funclist]) + " | ")
80
+ grammar2 = "\n".join(output)
81
+
82
+ parser_main = Lark(grammar2, start='start', parser='lalr')
83
+ parse_tree = parser_main.parse(equation)
84
+
85
+ # Convert Lark tree to TreeNode
86
+ def convert_to_treenode(parse_tree):
87
+ if isinstance(parse_tree, Tree):
88
+ node = TreeNode(parse_tree.data)
89
+ node.children = [convert_to_treenode(child) for child in parse_tree.children]
90
+ return node
91
+ else:
92
+ return TreeNode(str(parse_tree))
93
+
94
+ # Flatten unnecessary nodes like pass_through
95
+ def remove_past(equation):
96
+ if equation.name in {"number", "paren", "func", "variable", "pass_through", "cnumber", "string", "matrix"}:
97
+ if len(equation.children) == 1:
98
+ return remove_past(equation.children[0])
99
+ else:
100
+ equation.children = [remove_past(child) for child in equation.children]
101
+ return TreeNode(equation.children[0].name, equation.children[1:])
102
+ equation.children = [remove_past(child) for child in equation.children]
103
+ return equation
104
+
105
+ # Handle indices if any
106
+ def prefixindex(equation):
107
+ if equation.name == "base" and len(equation.children) > 1:
108
+ return TreeNode("index", [equation.children[0]] + equation.children[1].children)
109
+ return TreeNode(equation.name, [prefixindex(child) for child in equation.children])
110
+
111
+ tree_node = convert_to_treenode(parse_tree)
112
+ tree_node = remove_past(tree_node)
113
+ tree_node = prefixindex(tree_node)
114
+
115
+ # Convert function names and constants
116
+ def fxchange(tree_node):
117
+ tmp3 = funclist if funclist is not None else []
118
+ if tree_node.name == "neg":
119
+ child = fxchange(tree_node.children[0])
120
+ # if the child is a number, make it negative
121
+ if child.name.startswith("d_") and re.match(r"d_\d+(\.\d+)?$", child.name):
122
+ return TreeNode("d_" + str(-int(child.name[2:])))
123
+ else:
124
+ # otherwise subtract from zero
125
+ return TreeNode("f_sub", [tree_form("d_0"), child])
126
+ if tree_node.name == "pass_through":
127
+ return fxchange(tree_node.children[0])
128
+ return TreeNode(
129
+ "f_" + tree_node.name if tree_node.name in tmp3 + ["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,
130
+ [fxchange(child) for child in tree_node.children]
131
+ )
132
+
133
+ tree_node = fxchange(tree_node)
134
+
135
+ # Replace common constants
136
+ for const in ["e","pi","kc","em","ec","anot","hbar","false","true","i","nabla"]:
137
+ tree_node = replace(tree_node, tree_form("d_"+const), tree_form("s_"+const))
138
+
139
+ # Map letters to variables
140
+ for i, c in enumerate(["x","y","z"] + [chr(x+ord("a")) for x in range(0,23)]):
141
+ tree_node = replace(tree_node, tree_form("d_"+c), tree_form("v_"+str(i)))
142
+ for i, c in enumerate([chr(x+ord("A")) for x in range(0,26)]):
143
+ tree_node = replace(tree_node, tree_form("d_"+c), tree_form("v_-"+str(i+1)))
144
+ tree_node = replace(tree_node, tree_form("f_"+c), tree_form("v_-"+str(i+1)))
145
+
146
+ # Final recursive replacements
147
+ def rfx(tree_node):
148
+ if tree_node.name[:3] == "d_c":
149
+ return tree_form("v_" + str(int(tree_node.name[3:])+100))
150
+ tree_node.children = [rfx(child) for child in tree_node.children]
151
+ return tree_node
152
+
153
+ tree_node = rfx(tree_node)
154
+ return tree_node
mathai/printeq.py CHANGED
@@ -1,34 +1,34 @@
1
- from .base import *
2
- from .simplify import solve
3
- import copy
4
- from fractions import Fraction
5
- def abstractexpr(eq):
6
- if eq.name == "f_pow" and frac(eq.children[1])==Fraction(1,2):
7
- eq = eq.children[0].fx("sqrt")
8
- if eq.name == "f_pow" and frac(eq.children[1])==Fraction(-1,2):
9
- eq = eq.children[0].fx("sqrt")**-1
10
- if eq.name in ["f_mul", "f_pow"]:
11
-
12
- lst = factor_generation(eq)
13
- 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")
16
- if deno != []:
17
-
18
- num = [item for item in lst if item.name != "f_pow" or item.children[1].name[:3] != "d_-"]
19
- if num == []:
20
- num = [tree_form("d_1")]
21
- return TreeNode("f_div", [solve(product(num)), solve(product(deno))])
22
-
23
-
24
- return TreeNode(eq.name, [abstractexpr(child) for child in eq.children])
25
-
26
- def printeq_str(eq):
27
- return str(dowhile(copy.deepcopy(eq), abstractexpr))
28
-
29
- def printeq(eq):
30
- print(printeq_str(eq))
31
-
32
- def printeq_log(lst):
33
- for item in lst:
34
- print(" "*item[0] + item[1])
1
+ from .base import *
2
+ from .simplify import solve
3
+ import copy
4
+ from fractions import Fraction
5
+ def abstractexpr(eq):
6
+ if eq.name == "f_pow" and frac(eq.children[1])==Fraction(1,2):
7
+ eq = eq.children[0].fx("sqrt")
8
+ if eq.name == "f_pow" and frac(eq.children[1])==Fraction(-1,2):
9
+ eq = eq.children[0].fx("sqrt")**-1
10
+ if eq.name in ["f_mul", "f_pow"]:
11
+
12
+ lst = factor_generation(eq)
13
+ 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")
16
+ if deno != []:
17
+
18
+ num = [item for item in lst if item.name != "f_pow" or item.children[1].name[:3] != "d_-"]
19
+ if num == []:
20
+ num = [tree_form("d_1")]
21
+ return TreeNode("f_div", [solve(product(num)), solve(product(deno))])
22
+
23
+
24
+ return TreeNode(eq.name, [abstractexpr(child) for child in eq.children])
25
+
26
+ def printeq_str(eq):
27
+ return str(dowhile(copy.deepcopy(eq), abstractexpr))
28
+
29
+ def printeq(eq):
30
+ print(printeq_str(eq))
31
+
32
+ def printeq_log(lst):
33
+ for item in lst:
34
+ print(" "*item[0] + item[1])