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