mathai 0.2.8__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/simplify.py CHANGED
@@ -1,358 +1,358 @@
1
- import math
2
- from .base import *
3
- from fractions import Fraction
4
-
5
- def _solve(eq):
6
- def solve_add(eq):
7
- def multiplied(eq):
8
- if eq.name[:2] == "d_":
9
- return int(eq.name[2:]), "const"
10
- if eq.name == "f_mul":
11
- arth = 1
12
- for i in range(len(eq.children)-1,-1,-1):
13
- if eq.children[i].name[:2] == "d_":
14
- arth *= int(eq.children[i].name[2:])
15
- eq.children.pop(i)
16
- if eq.children == []:
17
- eq = "const"
18
- elif len(eq.children) == 1:
19
- eq = eq.children[0]
20
- return arth, eq
21
- return 1, eq
22
- if eq.name != "f_add":
23
- return eq
24
- dic = {"const":0}
25
- for child in eq.children:
26
- a, b = multiplied(child)
27
- if b == "const":
28
- dic[b] += a
29
- elif b in dic.keys():
30
- dic[b] += a
31
- else:
32
- dic[b] = a
33
- summation = TreeNode("f_add", [])
34
- for key in sorted(dic.keys(), key=lambda x: str_form(x)):
35
- n = dic[key]
36
- if n == 0:
37
- continue
38
- if key == "const":
39
- summation.children.append(tree_form("d_"+str(n)))
40
- else:
41
- if n == 1:
42
- summation.children.append(key)
43
- else:
44
- if key.name == "f_mul":
45
- key.children.append(tree_form("d_"+str(n)))
46
- else:
47
- key = tree_form("d_"+str(n))*key
48
- summation.children.append(key)
49
-
50
- if len(summation.children)==1:
51
- summation = summation.children[0]
52
-
53
- if summation.name[:2] == "f_" and len(summation.children)==0:
54
- summation = tree_form("d_0")
55
- return summation
56
-
57
- def solve_mul(eq):
58
- def multiplied(eq):
59
- if eq.name[:2] == "d_":
60
- return int(eq.name[2:]), "const"
61
- if eq.name != "f_pow" or eq.children[1].name[:2] != "d_":
62
- return 1, eq
63
- else:
64
- return int(eq.children[1].name[2:]), eq.children[0]
65
- if eq.name == "f_pow":
66
- if eq.children[1] == 1:
67
- return eq.children[0]
68
- return eq
69
- if eq.name != "f_mul":
70
- return eq
71
-
72
- dic = {"const":1}
73
- for child in eq.children:
74
-
75
- a, b = multiplied(child)
76
- if b == "const":
77
- dic[b] *= a
78
- elif b in dic.keys():
79
- dic[b] += a
80
- else:
81
- dic[b] = a
82
-
83
- summation = TreeNode("f_mul", [])
84
- if dic["const"] == 0:
85
- return tree_form("d_0")
86
- for key in sorted(dic.keys(), key=lambda x: str_form(x)):
87
- n = dic[key]
88
- if n == 0:
89
-
90
- continue
91
- if key == "const":
92
- if n != 1:
93
- summation.children.append(tree_form("d_"+str(n)))
94
- else:
95
- if n== 1:
96
- summation.children.append(key)
97
- else:
98
- summation.children.append(key**tree_form("d_"+str(n)))
99
-
100
- if len(summation.children)==1:
101
- summation = summation.children[0]
102
-
103
- if summation.name[:2] == "f_" and len(summation.children)==0:
104
- summation = tree_form("d_1")
105
-
106
- return summation
107
- def solve_u(eq):
108
- if eq.name in ["f_pow", "f_mul"]:
109
- return solve_mul(eq)
110
- return solve_add(eq)
111
- def recur_solve(eq):
112
- eq = solve_u(eq)
113
- if eq.children == []:
114
- pass
115
-
116
- elif eq.name in ("f_add", "f_mul"):
117
- merged_children = []
118
- for child in eq.children:
119
- if child.name == eq.name:
120
- merged_children.extend(child.children)
121
- else:
122
- merged_children.append(child)
123
-
124
- eq = TreeNode(eq.name, merged_children)
125
- return TreeNode(eq.name, [recur_solve(child) for child in eq.children])
126
-
127
- return recur_solve(eq)
128
- def _convert_sub2neg(eq):
129
- if eq.name == "f_neg":
130
- return -_convert_sub2neg(eq.children[0])
131
- elif eq.name == "f_sub":
132
- return _convert_sub2neg(eq.children[0]) - _convert_sub2neg(eq.children[1])
133
- elif eq.name == "f_sqrt":
134
- return _convert_sub2neg(eq.children[0])**(tree_form("d_2")**-1)
135
- elif eq.name == "f_div":
136
- if eq.children[0] == 0:
137
- return tree_form("d_0")
138
- return _convert_sub2neg(eq.children[0])*_convert_sub2neg(eq.children[1])**-1
139
- return TreeNode(eq.name, [_convert_sub2neg(child) for child in eq.children])
140
- def solve(eq, specialfx=False):
141
- if specialfx:
142
- eq = _convert_sub2neg(eq)
143
-
144
- eq = flatten_tree(eq)
145
-
146
- return dowhile(eq, _solve)
147
- def solve2(eq):
148
- return solve(eq, True)
149
- def clear_div(eq, denom=False):
150
- lst = factor_generation(eq)
151
- if tree_form("d_0") in lst:
152
- return tree_form("d_0")
153
- lst3 = [item for item in lst if "v_" not in str_form(item) and compute(item) < 0]
154
-
155
- sign = True
156
- if len(lst3) % 2 == 1:
157
- sign = False
158
- if denom:
159
- return eq if sign else -eq, sign
160
- lst = [item for item in lst if not(item.name == "f_pow" and frac(item.children[1]) is not None and frac(item.children[1]) == -1)]
161
-
162
- lst2 = [item for item in lst if "v_" in str_form(item)]
163
- if lst2 == []:
164
- return solve(product(lst)),sign
165
- return solve(product(lst2)),sign
166
-
167
- def simplify(eq):
168
- error = False
169
- eq = flatten_tree(eq)
170
- if eq.name in ["f_and", "f_or", "f_not"]:
171
- return TreeNode(eq.name, [simplify(child) for child in eq.children])
172
-
173
- if eq.name in ["f_lt", "f_gt", "f_le", "f_ge", "f_eq"]:
174
- tmp, sign = clear_div(simplify(eq.children[0]-eq.children[1]), eq.name != "f_eq")
175
- name2 = eq.name
176
- if not sign:
177
- name2 = {"f_lt":"f_gt", "f_gt":"f_lt", "f_eq":"f_eq", "f_le":"f_ge", "f_ge":"f_le"}[name2]
178
-
179
- return TreeNode(name2, [tmp, tree_form("d_0")])
180
-
181
- eq = solve(eq, True)
182
- def helper(eq):
183
-
184
- if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and eq.children[1].name[:2] == "d_":
185
-
186
- a, b = int(eq.children[0].name[2:]), int(eq.children[1].name[2:])
187
- a = a**abs(b)
188
- if b == 0 and a == 0:
189
- error= True
190
- return eq
191
- if b == 0:
192
- b = 1
193
- b = int(b/abs(b))
194
- if b == 1:
195
- eq = tree_form("d_"+str(a))
196
- else:
197
- eq = tree_form("d_"+str(a))**-1
198
- return TreeNode(eq.name, [helper(child) for child in eq.children])
199
- def helper2(eq):
200
-
201
- def even(eq):
202
- return eq.name[:2] == "d_" and int(eq.name[2:])%2==0
203
- def even2(eq):
204
- return any(even(item) for item in factor_generation(eq))
205
- if eq.name == "f_pow" and eq.children[0].name == "f_pow":
206
- if even2(eq.children[0].children[1]) or even2(eq.children[1]) and not even2(solve(eq.children[0].children[1] * eq.children[1])):
207
- return eq.children[0].children[0].fx("abs") ** solve(eq.children[0].children[1] * eq.children[1])
208
- else:
209
- return eq.children[0].children[0] ** solve(eq.children[0].children[1] * eq.children[1])
210
- return TreeNode(eq.name, [helper2(child) for child in eq.children])
211
- def helper3(eq):
212
-
213
- if eq.name == "f_mul":
214
- n = Fraction(1)
215
- for i in range(len(eq.children)-1,-1,-1):
216
- child= eq.children[i]
217
- if child.name == "f_pow" and child.children[0].name[:2] == "d_" and child.children[1] == -1:
218
- if int(child.children[0].name[2:]) == 0:
219
- error = True
220
- return eq
221
- n = n*Fraction(1,int(child.children[0].name[2:]))
222
- eq.children.pop(i)
223
- elif child.name[:2] == "d_":
224
- n = n*int(child.name[2:])
225
- eq.children.pop(i)
226
- if n.denominator == 1:
227
- eq.children.append(tree_form("d_"+str(n.numerator)))
228
- else:
229
- eq.children.append(tree_form("d_"+str(n.numerator))*tree_form("d_"+str(n.denominator))**-1)
230
-
231
- if len(eq.children) == 1:
232
- eq = eq.children[0]
233
- return TreeNode(eq.name, [helper3(child) for child in eq.children])
234
- def helper4(eq):
235
- nonlocal error
236
- if eq == tree_form("d_-1")**tree_form("d_-1"):
237
- return tree_form("d_-1")
238
- def perfect_nth_root_value(x, n):
239
- """Return integer y if x is a perfect n-th power (y**n == x), else None."""
240
- if x < 0 and n % 2 == 0:
241
- return None # even root of negative number not real
242
-
243
- sign = -1 if x < 0 else 1
244
- x = abs(x)
245
-
246
- # approximate integer root
247
- y = round(x ** (1.0 / n))
248
-
249
- if y ** n == x:
250
- return sign * y
251
- return None
252
- def pp(eq, n):
253
- if n == 1:
254
- return eq
255
- return eq**tree_form("d_"+str(n))
256
- if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and frac(eq.children[1]) is not None:
257
- f = frac(eq.children[1])
258
- r = f.denominator
259
- f = frac(eq.children[1]).numerator
260
- if r > 1:
261
- n = int(eq.children[0].name[2:])
262
- if n < 0 and r==2:
263
- out = perfect_nth_root_value(-n, 2)
264
- if out is not None:
265
- return pp( tree_form("d_"+str(out))*tree_form("s_i") , f)
266
- else:
267
- return pp( (tree_form("d_"+str(-n))**(tree_form("d_2")**-1))*tree_form("s_i"), f)
268
- else:
269
- out = perfect_nth_root_value(n, r)
270
- if out is not None:
271
- return pp( tree_form("d_"+str(out)), f)
272
- if eq.name == "f_mul" and len(eq.children)== 2:
273
- for i in range(2):
274
- if eq.children[i].name[:2] == "d_" and eq.children[1-i].name == "f_log":
275
- return (eq.children[1-i].children[0]**eq.children[i]).fx("log")
276
- if eq.name == "f_pow" and eq.children[0] == tree_form("s_e") and eq.children[1].name == "f_log":
277
- return eq.children[1].children[0]
278
- if eq.name == "f_pow" and eq.children[0] == tree_form("d_1"):
279
- eq = tree_form("d_1")
280
- if eq.name == "f_pow" and eq.children[0] == tree_form("d_0"):
281
- if frac(eq.children[1]) is not None and frac(eq.children[1]) <= 0:
282
- error = True
283
- else:
284
- eq = tree_form("d_0")
285
- if eq.name == "f_pow" and eq.children[0].name == "f_pow" and eq.children[0].children[1] == tree_form("d_2")**-1 and eq.children[1] == tree_form("d_2"):
286
- eq = eq.children[0].children[0]
287
- if (eq.name == "f_sin" and eq.children[0].name == "f_arcsin") or (eq.name == "f_cos" and eq.children[0].name == "f_arccos") or (eq.name == "f_tan" and eq.children[0].name == "f_arctan"):
288
- eq = eq.children[0].children[0]
289
- if (eq.name == "f_cos" and eq.children[0].name == "f_arcsin") or (eq.name == "f_sin" and eq.children[0].name == "f_arccos"):
290
- eq2 = eq.children[0].children[0]
291
- eq2 = (tree_form("d_1") - eq2*eq2)**(tree_form("d_1")/tree_form("d_2"))
292
- eq = eq2
293
- if (eq.name == "f_arcsin" and eq.children[0].name == "f_sin") or (eq.name == "f_arccos" and eq.children[0].name == "f_cos") or (eq.name == "f_arctan" and eq.children[0].name == "f_tan"):
294
- eq = eq.children[0].children[0]
295
- if eq.name == "f_abs" and eq.children[0].name[:2] == "d_":
296
- eq = tree_form("d_"+str(abs(int(eq.children[0].name[2:]))))
297
-
298
- if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and frac(eq.children[1]) is not None:
299
- f = frac(eq.children[1])
300
- if f.denominator != 1:
301
- return helper(eq.children[0]**tree_form("d_"+str(f.numerator)))**(tree_form("d_"+str(f.denominator))**-1)
302
-
303
- return TreeNode(eq.name, [helper4(child) for child in eq.children])
304
-
305
- def helper7(eq):
306
-
307
- if eq.name == "f_pow" and eq.children[0].name == "f_mul":
308
- return product([child**eq.children[1] for child in eq.children[0].children])
309
- return TreeNode(eq.name, [helper7(child) for child in eq.children])
310
-
311
- def helper6(eq):
312
- if eq.name == "f_mul":
313
- lst = factor_generation(eq)
314
- rm = []
315
- for i in range(len(lst)):
316
- if i in rm:
317
- continue
318
- for j in range(len(lst)):
319
- if i ==j or j in rm:
320
- continue
321
- if solve(helper2(lst[i]**-1)) == lst[j]:
322
- rm += [i,j]
323
- break
324
- if rm != []:
325
- for item in sorted(rm)[::-1]:
326
- lst.pop(item)
327
- return product(lst)
328
- return TreeNode(eq.name, [helper6(child) for child in eq.children])
329
- def helper5(eq):
330
-
331
- if eq.name == "f_pow" and eq.children[1].name[:2] == "d_" and abs(int(eq.children[1].name[2:]))%2==0 and eq.children[0].name == "f_abs":
332
- return eq.children[0].children[0]**eq.children[1]
333
- return TreeNode(eq.name, [helper5(child) for child in eq.children])
334
- def helper8(eq):
335
- if eq.name == "f_pow" and eq.children[0].name == "f_abs" and frac(eq.children[1]) is not None and frac(eq.children[1]).numerator % 2==0:
336
- return eq.children[0].children[0] ** eq.children[1]
337
- if eq.name == "f_abs" and eq.children[0].name == "f_abs":
338
- return eq.children[0]
339
- if eq.name == "f_cos" and eq.children[0].name == "f_abs":
340
- return eq.children[0].children[0].fx("cos")
341
- return TreeNode(eq.name, [helper8(child) for child in eq.children])
342
- def fx1(eq):
343
- for item in [helper, helper3, helper4, helper6,solve,helper2,helper5]:
344
- eq = dowhile(eq, item)
345
- return eq
346
- def fx2(eq):
347
- for item in [helper, helper3, helper4, helper6,helper7,helper2,helper5]:
348
- eq = dowhile(eq, item)
349
- return eq
350
- def fx3(eq):
351
- for item in [fx1, fx2]:
352
- eq = dowhile(eq, item)
353
- return eq
354
- eq = dowhile(eq, fx3)
355
- eq = dowhile(eq, helper8)
356
- if error:
357
- return None
358
- return solve(eq)
1
+ import math
2
+ from .base import *
3
+ from fractions import Fraction
4
+
5
+ def _solve(eq):
6
+ def solve_add(eq):
7
+ def multiplied(eq):
8
+ if eq.name[:2] == "d_":
9
+ return int(eq.name[2:]), "const"
10
+ if eq.name == "f_mul":
11
+ arth = 1
12
+ for i in range(len(eq.children)-1,-1,-1):
13
+ if eq.children[i].name[:2] == "d_":
14
+ arth *= int(eq.children[i].name[2:])
15
+ eq.children.pop(i)
16
+ if eq.children == []:
17
+ eq = "const"
18
+ elif len(eq.children) == 1:
19
+ eq = eq.children[0]
20
+ return arth, eq
21
+ return 1, eq
22
+ if eq.name != "f_add":
23
+ return eq
24
+ dic = {"const":0}
25
+ for child in eq.children:
26
+ a, b = multiplied(child)
27
+ if b == "const":
28
+ dic[b] += a
29
+ elif b in dic.keys():
30
+ dic[b] += a
31
+ else:
32
+ dic[b] = a
33
+ summation = TreeNode("f_add", [])
34
+ for key in sorted(dic.keys(), key=lambda x: str_form(x)):
35
+ n = dic[key]
36
+ if n == 0:
37
+ continue
38
+ if key == "const":
39
+ summation.children.append(tree_form("d_"+str(n)))
40
+ else:
41
+ if n == 1:
42
+ summation.children.append(key)
43
+ else:
44
+ if key.name == "f_mul":
45
+ key.children.append(tree_form("d_"+str(n)))
46
+ else:
47
+ key = tree_form("d_"+str(n))*key
48
+ summation.children.append(key)
49
+
50
+ if len(summation.children)==1:
51
+ summation = summation.children[0]
52
+
53
+ if summation.name[:2] == "f_" and len(summation.children)==0:
54
+ summation = tree_form("d_0")
55
+ return summation
56
+
57
+ def solve_mul(eq):
58
+ def multiplied(eq):
59
+ if eq.name[:2] == "d_":
60
+ return int(eq.name[2:]), "const"
61
+ if eq.name != "f_pow" or eq.children[1].name[:2] != "d_":
62
+ return 1, eq
63
+ else:
64
+ return int(eq.children[1].name[2:]), eq.children[0]
65
+ if eq.name == "f_pow":
66
+ if eq.children[1] == 1:
67
+ return eq.children[0]
68
+ return eq
69
+ if eq.name != "f_mul":
70
+ return eq
71
+
72
+ dic = {"const":1}
73
+ for child in eq.children:
74
+
75
+ a, b = multiplied(child)
76
+ if b == "const":
77
+ dic[b] *= a
78
+ elif b in dic.keys():
79
+ dic[b] += a
80
+ else:
81
+ dic[b] = a
82
+
83
+ summation = TreeNode("f_mul", [])
84
+ if dic["const"] == 0:
85
+ return tree_form("d_0")
86
+ for key in sorted(dic.keys(), key=lambda x: str_form(x)):
87
+ n = dic[key]
88
+ if n == 0:
89
+
90
+ continue
91
+ if key == "const":
92
+ if n != 1:
93
+ summation.children.append(tree_form("d_"+str(n)))
94
+ else:
95
+ if n== 1:
96
+ summation.children.append(key)
97
+ else:
98
+ summation.children.append(key**tree_form("d_"+str(n)))
99
+
100
+ if len(summation.children)==1:
101
+ summation = summation.children[0]
102
+
103
+ if summation.name[:2] == "f_" and len(summation.children)==0:
104
+ summation = tree_form("d_1")
105
+
106
+ return summation
107
+ def solve_u(eq):
108
+ if eq.name in ["f_pow", "f_mul"]:
109
+ return solve_mul(eq)
110
+ return solve_add(eq)
111
+ def recur_solve(eq):
112
+ eq = solve_u(eq)
113
+ if eq.children == []:
114
+ pass
115
+
116
+ elif eq.name in ("f_add", "f_mul"):
117
+ merged_children = []
118
+ for child in eq.children:
119
+ if child.name == eq.name:
120
+ merged_children.extend(child.children)
121
+ else:
122
+ merged_children.append(child)
123
+
124
+ eq = TreeNode(eq.name, merged_children)
125
+ return TreeNode(eq.name, [recur_solve(child) for child in eq.children])
126
+
127
+ return recur_solve(eq)
128
+ def _convert_sub2neg(eq):
129
+ if eq.name == "f_neg":
130
+ return -_convert_sub2neg(eq.children[0])
131
+ elif eq.name == "f_sub":
132
+ return _convert_sub2neg(eq.children[0]) - _convert_sub2neg(eq.children[1])
133
+ elif eq.name == "f_sqrt":
134
+ return _convert_sub2neg(eq.children[0])**(tree_form("d_2")**-1)
135
+ elif eq.name == "f_div":
136
+ if eq.children[0] == 0:
137
+ return tree_form("d_0")
138
+ return _convert_sub2neg(eq.children[0])*_convert_sub2neg(eq.children[1])**-1
139
+ return TreeNode(eq.name, [_convert_sub2neg(child) for child in eq.children])
140
+ def solve(eq, specialfx=False):
141
+ if specialfx:
142
+ eq = _convert_sub2neg(eq)
143
+
144
+ eq = flatten_tree(eq)
145
+
146
+ return dowhile(eq, _solve)
147
+ def solve2(eq):
148
+ return solve(eq, True)
149
+ def clear_div(eq, denom=False):
150
+ lst = factor_generation(eq)
151
+ if tree_form("d_0") in lst:
152
+ return tree_form("d_0"), True
153
+ lst3 = [item for item in lst if "v_" not in str_form(item) and compute(item) < 0]
154
+
155
+ sign = True
156
+ if len(lst3) % 2 == 1:
157
+ sign = False
158
+ if denom:
159
+ return eq if sign else -eq, sign
160
+ lst = [item for item in lst if not(item.name == "f_pow" and frac(item.children[1]) is not None and frac(item.children[1]) == -1)]
161
+
162
+ lst2 = [item for item in lst if "v_" in str_form(item)]
163
+ if lst2 == []:
164
+ return solve(product(lst)),sign
165
+ return solve(product(lst2)),sign
166
+
167
+ def simplify(eq):
168
+ error = False
169
+ eq = flatten_tree(eq)
170
+ if eq.name in ["f_and", "f_or", "f_not"]:
171
+ return TreeNode(eq.name, [simplify(child) for child in eq.children])
172
+
173
+ if eq.name in ["f_lt", "f_gt", "f_le", "f_ge", "f_eq"]:
174
+ tmp, sign = clear_div(simplify(eq.children[0]-eq.children[1]), eq.name != "f_eq")
175
+ name2 = eq.name
176
+ if not sign:
177
+ name2 = {"f_lt":"f_gt", "f_gt":"f_lt", "f_eq":"f_eq", "f_le":"f_ge", "f_ge":"f_le"}[name2]
178
+
179
+ return TreeNode(name2, [tmp, tree_form("d_0")])
180
+
181
+ eq = solve(eq, True)
182
+ def helper(eq):
183
+
184
+ if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and eq.children[1].name[:2] == "d_":
185
+
186
+ a, b = int(eq.children[0].name[2:]), int(eq.children[1].name[2:])
187
+ a = a**abs(b)
188
+ if b == 0 and a == 0:
189
+ error= True
190
+ return eq
191
+ if b == 0:
192
+ b = 1
193
+ b = int(b/abs(b))
194
+ if b == 1:
195
+ eq = tree_form("d_"+str(a))
196
+ else:
197
+ eq = tree_form("d_"+str(a))**-1
198
+ return TreeNode(eq.name, [helper(child) for child in eq.children])
199
+ def helper2(eq):
200
+
201
+ def even(eq):
202
+ return eq.name[:2] == "d_" and int(eq.name[2:])%2==0
203
+ def even2(eq):
204
+ return any(even(item) for item in factor_generation(eq))
205
+ if eq.name == "f_pow" and eq.children[0].name == "f_pow":
206
+ if even2(eq.children[0].children[1]) or even2(eq.children[1]) and not even2(solve(eq.children[0].children[1] * eq.children[1])):
207
+ return eq.children[0].children[0].fx("abs") ** solve(eq.children[0].children[1] * eq.children[1])
208
+ else:
209
+ return eq.children[0].children[0] ** solve(eq.children[0].children[1] * eq.children[1])
210
+ return TreeNode(eq.name, [helper2(child) for child in eq.children])
211
+ def helper3(eq):
212
+
213
+ if eq.name == "f_mul":
214
+ n = Fraction(1)
215
+ for i in range(len(eq.children)-1,-1,-1):
216
+ child= eq.children[i]
217
+ if child.name == "f_pow" and child.children[0].name[:2] == "d_" and child.children[1] == -1:
218
+ if int(child.children[0].name[2:]) == 0:
219
+ error = True
220
+ return eq
221
+ n = n*Fraction(1,int(child.children[0].name[2:]))
222
+ eq.children.pop(i)
223
+ elif child.name[:2] == "d_":
224
+ n = n*int(child.name[2:])
225
+ eq.children.pop(i)
226
+ if n.denominator == 1:
227
+ eq.children.append(tree_form("d_"+str(n.numerator)))
228
+ else:
229
+ eq.children.append(tree_form("d_"+str(n.numerator))*tree_form("d_"+str(n.denominator))**-1)
230
+
231
+ if len(eq.children) == 1:
232
+ eq = eq.children[0]
233
+ return TreeNode(eq.name, [helper3(child) for child in eq.children])
234
+ def helper4(eq):
235
+ nonlocal error
236
+ if eq == tree_form("d_-1")**tree_form("d_-1"):
237
+ return tree_form("d_-1")
238
+ def perfect_nth_root_value(x, n):
239
+ """Return integer y if x is a perfect n-th power (y**n == x), else None."""
240
+ if x < 0 and n % 2 == 0:
241
+ return None # even root of negative number not real
242
+
243
+ sign = -1 if x < 0 else 1
244
+ x = abs(x)
245
+
246
+ # approximate integer root
247
+ y = round(x ** (1.0 / n))
248
+
249
+ if y ** n == x:
250
+ return sign * y
251
+ return None
252
+ def pp(eq, n):
253
+ if n == 1:
254
+ return eq
255
+ return eq**tree_form("d_"+str(n))
256
+ if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and frac(eq.children[1]) is not None:
257
+ f = frac(eq.children[1])
258
+ r = f.denominator
259
+ f = frac(eq.children[1]).numerator
260
+ if r > 1:
261
+ n = int(eq.children[0].name[2:])
262
+ if n < 0 and r==2:
263
+ out = perfect_nth_root_value(-n, 2)
264
+ if out is not None:
265
+ return pp( tree_form("d_"+str(out))*tree_form("s_i") , f)
266
+ else:
267
+ return pp( (tree_form("d_"+str(-n))**(tree_form("d_2")**-1))*tree_form("s_i"), f)
268
+ else:
269
+ out = perfect_nth_root_value(n, r)
270
+ if out is not None:
271
+ return pp( tree_form("d_"+str(out)), f)
272
+ if eq.name == "f_mul" and len(eq.children)== 2:
273
+ for i in range(2):
274
+ if eq.children[i].name[:2] == "d_" and eq.children[1-i].name == "f_log":
275
+ return (eq.children[1-i].children[0]**eq.children[i]).fx("log")
276
+ if eq.name == "f_pow" and eq.children[0] == tree_form("s_e") and eq.children[1].name == "f_log":
277
+ return eq.children[1].children[0]
278
+ if eq.name == "f_pow" and eq.children[0] == tree_form("d_1"):
279
+ eq = tree_form("d_1")
280
+ if eq.name == "f_pow" and eq.children[0] == tree_form("d_0"):
281
+ if frac(eq.children[1]) is not None and frac(eq.children[1]) <= 0:
282
+ error = True
283
+ else:
284
+ eq = tree_form("d_0")
285
+ if eq.name == "f_pow" and eq.children[0].name == "f_pow" and eq.children[0].children[1] == tree_form("d_2")**-1 and eq.children[1] == tree_form("d_2"):
286
+ eq = eq.children[0].children[0]
287
+ if (eq.name == "f_sin" and eq.children[0].name == "f_arcsin") or (eq.name == "f_cos" and eq.children[0].name == "f_arccos") or (eq.name == "f_tan" and eq.children[0].name == "f_arctan"):
288
+ eq = eq.children[0].children[0]
289
+ if (eq.name == "f_cos" and eq.children[0].name == "f_arcsin") or (eq.name == "f_sin" and eq.children[0].name == "f_arccos"):
290
+ eq2 = eq.children[0].children[0]
291
+ eq2 = (tree_form("d_1") - eq2*eq2)**(tree_form("d_1")/tree_form("d_2"))
292
+ eq = eq2
293
+ if (eq.name == "f_arcsin" and eq.children[0].name == "f_sin") or (eq.name == "f_arccos" and eq.children[0].name == "f_cos") or (eq.name == "f_arctan" and eq.children[0].name == "f_tan"):
294
+ eq = eq.children[0].children[0]
295
+ if eq.name == "f_abs" and eq.children[0].name[:2] == "d_":
296
+ eq = tree_form("d_"+str(abs(int(eq.children[0].name[2:]))))
297
+
298
+ if eq.name == "f_pow" and eq.children[0].name[:2] == "d_" and frac(eq.children[1]) is not None:
299
+ f = frac(eq.children[1])
300
+ if f.denominator != 1:
301
+ return helper(eq.children[0]**tree_form("d_"+str(f.numerator)))**(tree_form("d_"+str(f.denominator))**-1)
302
+
303
+ return TreeNode(eq.name, [helper4(child) for child in eq.children])
304
+
305
+ def helper7(eq):
306
+
307
+ if eq.name == "f_pow" and eq.children[0].name == "f_mul":
308
+ return product([child**eq.children[1] for child in eq.children[0].children])
309
+ return TreeNode(eq.name, [helper7(child) for child in eq.children])
310
+
311
+ def helper6(eq):
312
+ if eq.name == "f_mul":
313
+ lst = factor_generation(eq)
314
+ rm = []
315
+ for i in range(len(lst)):
316
+ if i in rm:
317
+ continue
318
+ for j in range(len(lst)):
319
+ if i ==j or j in rm:
320
+ continue
321
+ if solve(helper2(lst[i]**-1)) == lst[j]:
322
+ rm += [i,j]
323
+ break
324
+ if rm != []:
325
+ for item in sorted(rm)[::-1]:
326
+ lst.pop(item)
327
+ return product(lst)
328
+ return TreeNode(eq.name, [helper6(child) for child in eq.children])
329
+ def helper5(eq):
330
+
331
+ if eq.name == "f_pow" and eq.children[1].name[:2] == "d_" and abs(int(eq.children[1].name[2:]))%2==0 and eq.children[0].name == "f_abs":
332
+ return eq.children[0].children[0]**eq.children[1]
333
+ return TreeNode(eq.name, [helper5(child) for child in eq.children])
334
+ def helper8(eq):
335
+ if eq.name == "f_pow" and eq.children[0].name == "f_abs" and frac(eq.children[1]) is not None and frac(eq.children[1]).numerator % 2==0:
336
+ return eq.children[0].children[0] ** eq.children[1]
337
+ if eq.name == "f_abs" and eq.children[0].name == "f_abs":
338
+ return eq.children[0]
339
+ if eq.name == "f_cos" and eq.children[0].name == "f_abs":
340
+ return eq.children[0].children[0].fx("cos")
341
+ return TreeNode(eq.name, [helper8(child) for child in eq.children])
342
+ def fx1(eq):
343
+ for item in [helper, helper3, helper4, helper6,solve,helper2,helper5]:
344
+ eq = dowhile(eq, item)
345
+ return eq
346
+ def fx2(eq):
347
+ for item in [helper, helper3, helper4, helper6,helper7,helper2,helper5]:
348
+ eq = dowhile(eq, item)
349
+ return eq
350
+ def fx3(eq):
351
+ for item in [fx1, fx2]:
352
+ eq = dowhile(eq, item)
353
+ return eq
354
+ eq = dowhile(eq, fx3)
355
+ eq = dowhile(eq, helper8)
356
+ if error:
357
+ return None
358
+ return solve(eq)