mathai 0.4.6__tar.gz → 0.4.8__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 (31) hide show
  1. {mathai-0.4.6 → mathai-0.4.8}/PKG-INFO +4 -1
  2. {mathai-0.4.6 → mathai-0.4.8}/README.md +3 -0
  3. {mathai-0.4.6 → mathai-0.4.8}/mathai/__init__.py +5 -2
  4. {mathai-0.4.6 → mathai-0.4.8}/mathai/apart.py +28 -9
  5. {mathai-0.4.6 → mathai-0.4.8}/mathai/base.py +1 -1
  6. {mathai-0.4.6 → mathai-0.4.8}/mathai/factor.py +93 -33
  7. {mathai-0.4.6 → mathai-0.4.8}/mathai/integrate.py +39 -5
  8. {mathai-0.4.6 → mathai-0.4.8}/mathai/limit.py +2 -0
  9. {mathai-0.4.6 → mathai-0.4.8}/mathai/simplify.py +12 -1
  10. mathai-0.4.8/mathai/tool.py +163 -0
  11. {mathai-0.4.6 → mathai-0.4.8}/mathai/trig.py +58 -47
  12. {mathai-0.4.6 → mathai-0.4.8}/mathai.egg-info/PKG-INFO +4 -1
  13. {mathai-0.4.6 → mathai-0.4.8}/setup.py +1 -1
  14. mathai-0.4.6/mathai/tool.py +0 -62
  15. {mathai-0.4.6 → mathai-0.4.8}/mathai/console.py +0 -0
  16. {mathai-0.4.6 → mathai-0.4.8}/mathai/diff.py +0 -0
  17. {mathai-0.4.6 → mathai-0.4.8}/mathai/expand.py +0 -0
  18. {mathai-0.4.6 → mathai-0.4.8}/mathai/fraction.py +0 -0
  19. {mathai-0.4.6 → mathai-0.4.8}/mathai/inverse.py +0 -0
  20. {mathai-0.4.6 → mathai-0.4.8}/mathai/linear.py +0 -0
  21. {mathai-0.4.6 → mathai-0.4.8}/mathai/logic.py +0 -0
  22. {mathai-0.4.6 → mathai-0.4.8}/mathai/ode.py +0 -0
  23. {mathai-0.4.6 → mathai-0.4.8}/mathai/parser.py +0 -0
  24. {mathai-0.4.6 → mathai-0.4.8}/mathai/printeq.py +0 -0
  25. {mathai-0.4.6 → mathai-0.4.8}/mathai/structure.py +0 -0
  26. {mathai-0.4.6 → mathai-0.4.8}/mathai/univariate_inequality.py +0 -0
  27. {mathai-0.4.6 → mathai-0.4.8}/mathai.egg-info/SOURCES.txt +0 -0
  28. {mathai-0.4.6 → mathai-0.4.8}/mathai.egg-info/dependency_links.txt +0 -0
  29. {mathai-0.4.6 → mathai-0.4.8}/mathai.egg-info/requires.txt +0 -0
  30. {mathai-0.4.6 → mathai-0.4.8}/mathai.egg-info/top_level.txt +0 -0
  31. {mathai-0.4.6 → mathai-0.4.8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 0.4.6
3
+ Version: 0.4.8
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
@@ -16,6 +16,9 @@ Dynamic: requires-python
16
16
  Dynamic: summary
17
17
 
18
18
  # Math AI Documentation
19
+ ## Source
20
+ Github repository of the code
21
+ https://github.com/infinity390/mathai4
19
22
 
20
23
  ## Philosophy
21
24
  I think it is a big realization in computer science and programming to realize that computers can solve mathematics.
@@ -1,4 +1,7 @@
1
1
  # Math AI Documentation
2
+ ## Source
3
+ Github repository of the code
4
+ https://github.com/infinity390/mathai4
2
5
 
3
6
  ## Philosophy
4
7
  I think it is a big realization in computer science and programming to realize that computers can solve mathematics.
@@ -1,6 +1,8 @@
1
1
  from .ode import diffsolve as ode_solve
2
2
  from .ode import diffsolve_sep as ode_shift_term
3
3
 
4
+ from .linear import linear_solve
5
+
4
6
  from .expand import expand
5
7
 
6
8
  from .parser import parse
@@ -35,7 +37,7 @@ from .trig import trig0, trig1, trig2, trig3, trig4
35
37
 
36
38
  from .logic import logic0, logic1, logic2, logic3
37
39
 
38
- from .apart import apart
40
+ from .apart import apart, apart2
39
41
 
40
42
  from .console import console
41
43
 
@@ -46,4 +48,5 @@ from .univariate_inequality import wavycurvy, absolute, domain, handle_sqrt
46
48
  from .base import *
47
49
 
48
50
  from .tool import enclose_const
49
-
51
+ from .tool import poly_simplify
52
+ from .tool import longdiv
@@ -6,19 +6,23 @@ from .diff import diff
6
6
  from .inverse import inverse
7
7
  from .base import *
8
8
  import math
9
- from .tool import poly, enclose_const
9
+ from .factor import factor2
10
+ from .tool import poly, enclose_const, longdiv
10
11
 
11
12
  def _apart(eq, v=None):
13
+
12
14
  if v is None:
13
15
  if len(vlist(eq)) == 0:
14
16
  return eq
15
17
  v = vlist(eq)[0]
16
18
  origv = vlist(eq)
17
- eq = simplify(eq)
19
+
18
20
  if eq.name != "f_mul":
19
21
  return eq
22
+
20
23
  if any("f_"+item in str_form(eq) for item in "sin cos tan log".split(" ")):
21
24
  return eq
25
+
22
26
  def exclude(eq):
23
27
  if eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]).denominator != 1:
24
28
  return False
@@ -48,7 +52,7 @@ def _apart(eq, v=None):
48
52
 
49
53
 
50
54
  facd2 = remove_duplicates_custom(facd, lambda m, n: simplify(expand(simplify(m-n))) == tree_form("d_0"))
51
-
55
+
52
56
  if len(facd2) == 1:
53
57
  return eq
54
58
  x = tree_form(v)
@@ -60,7 +64,7 @@ def _apart(eq, v=None):
60
64
  g = countfac(facd, item)
61
65
  for n in range(int(g.name[2:])):
62
66
  n = n+1
63
- if n > 2:
67
+ if n > 3:
64
68
  return eq
65
69
  n = tree_form("d_"+str(n))
66
70
 
@@ -87,6 +91,7 @@ def _apart(eq, v=None):
87
91
  dem.append(item**n)
88
92
  s.append(a/item**n)
89
93
  else:
94
+
90
95
  return eq
91
96
  final3 = summation(s)
92
97
 
@@ -95,13 +100,13 @@ def _apart(eq, v=None):
95
100
  final2 = []
96
101
  for i in range(len(num)):
97
102
  final2.append(product([dem[k] for k in range(len(dem)) if i != k])*num[i])
98
-
103
+
99
104
  final = summation(final2)
100
-
105
+
101
106
  s = simplify(TreeNode("f_eq", [final-eq2, tree_form("d_0")]))
102
-
107
+
103
108
  lst = poly(s.children[0], v)
104
-
109
+
105
110
  lst = [TreeNode("f_eq", [item, tree_form("d_0")]) for item in lst if "v_" in str_form(item)]
106
111
  lst2 = []
107
112
  for item in lst:
@@ -112,12 +117,26 @@ def _apart(eq, v=None):
112
117
  for item in out.children:
113
118
 
114
119
  final3 = replace(final3, tree_form(list(set(vlist(item))&set(origv))[0]), inverse(item.children[0], list(set(vlist(item))&set(origv))[0]))
115
- return simplify(final3)
120
+ final4 = simplify(final3)
121
+
122
+ return final4
123
+ def apart2(eq):
124
+ if eq.name == "f_mul":
125
+
126
+ a, b = num_dem(eq)
127
+
128
+ tmp = longdiv(a, b, 2, 1)
129
+
130
+ if tmp is not None:
131
+ return simplify(tmp[0]+tmp[1]/b)
132
+ return TreeNode(eq.name, [apart2(child) for child in eq.children])
116
133
  def apart(eq):
134
+ eq = factor2(simplify(eq))
117
135
  eq, fx = enclose_const(eq)
118
136
  def helper(eq):
119
137
  eq2 = _apart(eq)
120
138
  if eq != eq2:
121
139
  return eq2
140
+
122
141
  return TreeNode(eq.name, [helper(child) for child in eq.children])
123
142
  return fx(helper(eq))
@@ -255,7 +255,7 @@ def num_dem(equation):
255
255
  return [num, tree_form("d_1")/den]
256
256
 
257
257
  def summation(lst):
258
- if lst == []:
258
+ if len(lst) == 0:
259
259
  return tree_form("d_0")
260
260
  s = lst[0]
261
261
  for item in lst[1:]:
@@ -5,6 +5,7 @@ from .base import *
5
5
  from .simplify import simplify,solve
6
6
  from .expand import expand
7
7
  import math
8
+ from .tool import poly
8
9
 
9
10
  from collections import Counter
10
11
  def multiset_intersection(*lists):
@@ -42,6 +43,7 @@ def take_common(eq):
42
43
  eq2 = term_common(eq2)
43
44
  if eq2.name == "f_mul":
44
45
  return take_common(solve(summation([item2 for index, item2 in enumerate(eq.children) if index not in item]) + eq2))
46
+ break
45
47
  return eq
46
48
  return term_common(eq)
47
49
  def take_common2(eq):
@@ -158,12 +160,6 @@ def rationalize_sqrt(eq):
158
160
  return TreeNode(eq.name, [rationalize_sqrt(child) for child in eq.children])
159
161
  def factorconst(eq):
160
162
  return simplify(_factorconst(eq))
161
- def factor_quad_formula_init():
162
- var = ""
163
- formula_list = [(f"(A*D^2+B*D+C)", f"A*(D-(-B+(B^2-4*A*C)^(1/2))/(2*A))*(D-(-B-(B^2-4*A*C)^(1/2))/(2*A))")]
164
- formula_list = [[simplify(parse(y)) for y in x] for x in formula_list]
165
- expr = [[parse("A"), parse("1")], [parse("B"), parse("0"), parse("1")], [parse("C"), parse("0")]]
166
- return [formula_list, var, expr]
167
163
 
168
164
  def factor_quar_formula_init():
169
165
  var = ""
@@ -171,51 +167,115 @@ def factor_quar_formula_init():
171
167
  formula_list = [[simplify(parse(y)) for y in x] for x in formula_list]
172
168
  expr = [[parse("A")], [parse("B"), parse("0"), parse("1")], [parse("C"), parse("0")]]
173
169
  return [formula_list, var, expr]
174
- def factor_cube_formula_init():
175
- var = ""
176
- formula_list = [(f"D^3+E", f"(D+E^(1/3))*(D^2-D*E^(1/3)+E^(2/3))"), (f"D^3-E", f"(D-E^(1/3))*(D^2+D*E^(1/3)+E^(2/3))"),\
177
- (f"-D^3+E", f"(-D+E^(1/3))*(D^2+D*E^(1/3)+E^(2/3))")]
178
- formula_list = [[simplify(parse(y)) for y in x] for x in formula_list]
179
- expr = [[parse("A")], [parse("B")]]
180
- return [formula_list, var, expr]
181
- formula_gen2 = factor_quad_formula_init()
182
- formula_gen3 = factor_cube_formula_init()
170
+
183
171
  formula_gen9 = factor_quar_formula_init()
184
172
  def factor_helper(equation, complexnum, power=2):
185
- global formula_gen2, formula_gen3, formula_gen9
186
- maxnum = 1
173
+ global formula_gen9
174
+
175
+ maxnum=1
176
+ alloclst = []
177
+ for i in range(0,26):
178
+ if "v_"+str(i) not in vlist(equation):
179
+ alloclst.append("v_"+str(i))
180
+ r = alloclst.pop(0)
181
+ fx = None
182
+ curr = None
187
183
  def high(eq):
188
184
  nonlocal maxnum
189
185
  if eq.name == "f_pow" and eq.children[1].name[:2] == "d_":
190
186
  n = int(eq.children[1].name[2:])
191
- if n>power and n % power == 0:
192
- maxnum = max(maxnum, n)
187
+ if abs(n)>power and abs(n) % power == 0:
188
+ if abs(n)>abs(maxnum):
189
+ maxnum = n
193
190
  for child in eq.children:
194
191
  high(child)
195
192
  def helper(eq):
196
- nonlocal maxnum
197
- if eq.name == "f_pow" and eq.children[1].name[:2] == "d_":
193
+ nonlocal maxnum, fx, r
194
+ if eq.name == "f_pow" and eq.children[1].name[:2] == "d_" and eq.children[0] == curr:
198
195
  n = int(eq.children[1].name[2:])
199
- sgn = round(abs(n)/n)
200
- n = abs(n)
201
- if n>power and n % power == 0 and maxnum==n:
202
- out= (eq.children[0]**tree_form("d_"+str(sgn*int(n/power))))**power
196
+ if maxnum !=1 and n % maxnum == 0:
197
+ fx = lambda x: replace(x, tree_form(r), curr**tree_form("d_"+str(maxnum)))
198
+ out= tree_form(r)**tree_form("d_"+str(int(n/maxnum)))
203
199
  return out
204
200
  return TreeNode(eq.name, [helper(child) for child in eq.children])
205
- high(equation)
206
201
  out = None
207
- if power == 2:
208
- out = transform_formula(helper(equation), "v_0", formula_gen2[0], formula_gen2[1], formula_gen2[2])
209
- elif power == 3:
210
- out = transform_formula(helper(equation), "v_0", formula_gen3[0], formula_gen3[1], formula_gen3[2])
211
- elif power == 4:
202
+
203
+ for i in range(2,4):
204
+ if power == i:
205
+ for curr in vlist(equation):
206
+ curr = tree_form(curr)
207
+ fx = None
208
+ maxnum = 1
209
+ high(equation.copy_tree())
210
+
211
+ if maxnum != 1:
212
+ maxnum= maxnum/power
213
+ maxnum = round(maxnum)
214
+ eq2 = helper(equation.copy_tree())
215
+ if not contain(eq2, tree_form(r)) or (contain(eq2, tree_form(r)) and not contain(eq2,curr)):
216
+ if not contain(eq2, tree_form(r)):
217
+ r = curr.name
218
+ fx = lambda x: x
219
+
220
+ lst = poly(eq2.copy_tree(), r)
221
+ if lst is not None and len(lst)==i+1:
222
+
223
+ success = True
224
+ if i == 2:
225
+ a, b, c = lst
226
+ x1 = (-b+(b**2 - 4*a*c)**(tree_form("d_2")**-1))/(2*a)
227
+ x2 = (-b-(b**2 - 4*a*c)**(tree_form("d_2")**-1))/(2*a)
228
+ x1 = simplify(x1)
229
+ x2 = simplify(x2)
230
+ eq2 = a*(tree_form(r)-x1)*(tree_form(r)-x2)
231
+ if not complexnum and (contain(x1, tree_form("s_i")) or contain(x2, tree_form("s_i"))):
232
+ success = False
233
+ else:
234
+ a, b, c, d = lst
235
+ B, C, D = b/a, c/a, d/a
236
+ p = C-(B**2)/3
237
+ q = 2*B**3/27-B*C/3+D
238
+ t = q**2/4+ p**3/27
239
+ u = (-q/2+t**(tree_form("d_2")**-1))**(tree_form("d_3")**-1)
240
+ v = (-q/2-t**(tree_form("d_2")**-1))**(tree_form("d_3")**-1)
241
+ y1 = u+v
242
+ three = 3**(tree_form("d_2")**-1)
243
+ y2 = -(u+v)/2+tree_form("s_i")*three*(u-v)/2
244
+ y3 = -(u+v)/2-tree_form("s_i")*three*(u-v)/2
245
+ x1,x2,x3 = y1-B/3 , y2-B/3, y3-B/3
246
+ x1,x2, x3 = simplify(x1), simplify(x2), simplify(x3)
247
+ out2 = None
248
+ if not complexnum:
249
+ for item in itertools.combinations([x1,x2,x3],2):
250
+ if all(contain(item2,tree_form("s_i")) for item2 in list(item)):
251
+ out2 = (tree_form(r)-item[0])*(tree_form(r)-item[1])
252
+ break
253
+ if out2 is not None:
254
+ out2 = simplify(expand(simplify(out2)))
255
+ out3 = None
256
+ for item in [x1, x2, x3]:
257
+ if not contain(item,tree_form("s_i")):
258
+ out3 = item
259
+ break
260
+ eq2 = a*(tree_form(r)-out3)*out2
261
+
262
+ else:
263
+ eq2 = a*(tree_form(r)-x1)*(tree_form(r)-x2)*(tree_form(r)-x3)
264
+ if success:
265
+ equation = fx(eq2)
266
+ break
267
+
268
+ if power == 4:
269
+
212
270
  out = transform_formula(helper(equation), "v_0", formula_gen9[0], formula_gen9[1], formula_gen9[2])
271
+
213
272
  if out is not None:
214
273
  out = simplify(solve(out))
215
274
  if out is not None and (complexnum or (not complexnum and not contain(out, tree_form("s_i")))):
216
275
  return out
276
+
217
277
  return TreeNode(equation.name, [factor_helper(child, complexnum, power) for child in equation.children])
218
- def factor(equation, complexnum=False):
219
- return solve(take_common2(simplify(factor_helper(simplify(equation), complexnum, 2))))
278
+ def factor(equation):
279
+ return solve(take_common2(simplify(equation)))
220
280
  def factor2(equation, complexnum=False):
221
281
  return solve(factor_helper(solve(factor_helper(simplify(factor_helper(simplify(equation), complexnum, 2)), complexnum, 3)), complexnum, 4))
@@ -31,8 +31,13 @@ def integrate_summation(equation):
31
31
  def subs_heuristic(eq, var):
32
32
  output = []
33
33
  def collect2(eq):
34
+ if eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]) == Fraction(1,2):
35
+
36
+ if eq.children[0] == var:
37
+ output.append(str_form(eq))
34
38
  if eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]).denominator == 1 and abs(frac(eq.children[1]).numerator) % 2 == 0:
35
- output.append(str_form(eq.children[0]**2))
39
+ if len(eq.children[0].children) == 0 or eq.children[0].children[0] == var:
40
+ output.append(str_form(eq.children[0]**2))
36
41
  if eq.name in ["f_pow", "f_sin", "f_cos", "f_arcsin"] and var.name in str_form(eq.children[0]):
37
42
  if eq.children[0].name[:2] != "v_":
38
43
  output.append(str_form(eq.children[0]))
@@ -57,7 +62,20 @@ def subs_heuristic(eq, var):
57
62
 
58
63
  tmp = list(set([simplify(tree_form(x)) for x in output]))
59
64
  tmp = sorted(tmp, key=lambda x: len(str(x)))
60
- return tmp
65
+ poly_term = None
66
+ term_degree = 100
67
+ output = []
68
+ for item in tmp:
69
+ n = poly(simplify(item), var.name)
70
+ if n is None:
71
+ output.append(item)
72
+ else:
73
+ if term_degree > len(n):
74
+ poly_term = item
75
+ term_degree = len(n)
76
+ if poly_term is None:
77
+ return tmp
78
+ return [poly_term]+output
61
79
  try_index = []
62
80
  try_lst = []
63
81
  def ref(eq):
@@ -170,7 +188,7 @@ def integrate_subs(equation, term, v1, v2):
170
188
 
171
189
  return none
172
190
 
173
- return TreeNode("f_subs", [TreeNode("f_integrate", [simplify(fraction(expand(simplify(equation)))), tree_form(origv2)]),tree_form(origv2) ,g])
191
+ return TreeNode("f_subs", [TreeNode("f_integrate", [simplify(equation), tree_form(origv2)]),tree_form(origv2) ,g])
174
192
 
175
193
  def integrate_subs_main(equation):
176
194
  if equation.name == "f_ref":
@@ -359,10 +377,21 @@ def integration_formula_trig():
359
377
  [parse("C"), parse("0"), parse("1")], [parse("D"), parse("0"), parse("1")],\
360
378
  [parse("E"), parse("0"), parse("1")], [parse("F"), parse("0"), parse("1")]]
361
379
  return [formula_list, var, expr]
362
-
363
-
364
380
  formula_gen4 = integration_formula_trig()
365
381
 
382
+ def integration_formula_ex():
383
+ var = "x"
384
+ formula_list = [
385
+ (
386
+ f"e^(A*{var})*cos(B*{var})",
387
+ f"e^(A*{var})*(A*cos(B*{var}) + B*sin(B*{var}))/(A^2 + B^2)"
388
+ )
389
+ ]
390
+ formula_list = [[simplify(parse(y)) for y in x] for x in formula_list]
391
+ expr = [[parse("A"), parse("1")], [parse("B"), parse("1")]]
392
+ return [formula_list, var, expr]
393
+
394
+ formula_gen11 = integration_formula_ex()
366
395
  def rm_const(equation):
367
396
  if equation.name == "f_ref":
368
397
  return equation
@@ -406,4 +435,9 @@ def integrate_formula(equation):
406
435
  if out is not None:
407
436
 
408
437
  return out
438
+ if "f_cos" in expr_str and contain(integrand, tree_form("s_e")):
439
+ out = transform_formula(integrand, wrt.name, formula_gen11[0], formula_gen11[1], formula_gen11[2])
440
+ if out is not None:
441
+
442
+ return out
409
443
  return TreeNode(eq2.name, [integrate_formula(child) for child in eq2.children])
@@ -14,6 +14,7 @@ def substitute_val(eq, val, var="v_0"):
14
14
 
15
15
  def subslimit(equation, var):
16
16
  equation2 = trig0(replace(equation, var, tree_form("d_0")))
17
+
17
18
  try:
18
19
  tmp = simplify(equation2)
19
20
  return simplify(expand(tmp))
@@ -35,6 +36,7 @@ def lhospital(num, den, steps,var):
35
36
  logs = []
36
37
 
37
38
  out = check(num, den, var)
39
+
38
40
  if isinstance(out, TreeNode):
39
41
  return out,[]
40
42
  for _ in range(steps):
@@ -168,6 +168,15 @@ def clear_div(eq, denom=False):
168
168
  return solve(product(lst2)),sign
169
169
 
170
170
  def simplify(eq):
171
+ if "v_" not in str_form(eq):
172
+ n = frac(eq)
173
+ if n is not None:
174
+ if n.numerator == 0:
175
+ return tree_form("d_0")
176
+ if n.denominator != 1:
177
+ return tree_form("d_"+str(n.numerator))/tree_form("d_"+str(n.denominator))
178
+ else:
179
+ return tree_form("d_"+str(n.numerator))
171
180
  error = False
172
181
  eq = flatten_tree(eq)
173
182
  if eq.name in ["f_and", "f_or", "f_not"]:
@@ -287,7 +296,9 @@ def simplify(eq):
287
296
  error = True
288
297
  else:
289
298
  eq = tree_form("d_0")
290
-
299
+ if eq.name =="f_pow" and eq.children[0] == tree_form("s_i") and frac(eq.children[1])is not None and frac(eq.children[1]).denominator == 1:
300
+ n = frac(eq.children[1]).numerator
301
+ eq = {0:tree_form("d_1"), 1:tree_form("s_i"), 2:tree_form("d_-1"), 3:-tree_form("s_i")}[n%4]
291
302
  if eq.name == "f_mul":
292
303
  dic = {}
293
304
  for child in eq.children:
@@ -0,0 +1,163 @@
1
+ from .diff import diff
2
+ from .expand import expand
3
+ from .simplify import simplify, solve
4
+ from .base import *
5
+ import math
6
+
7
+ def poly_div(dividend_coeffs, divisor_coeffs):
8
+ """
9
+ Perform polynomial division using coefficients with symbolic simplification.
10
+ """
11
+ # Deep copy inputs using copy_tree()
12
+ dividend = [item.copy_tree() for item in dividend_coeffs]
13
+ divisor = [item.copy_tree() for item in divisor_coeffs]
14
+
15
+ # Remove leading zeros
16
+ while len(dividend) > 1 and simplify(dividend[0]) == 0:
17
+ dividend.pop(0)
18
+ while len(divisor) > 1 and simplify(divisor[0]) == 0:
19
+ divisor.pop(0)
20
+
21
+ # Validate divisor
22
+ if len(divisor) == 0 or simplify(divisor[0]) == 0:
23
+ raise ValueError("Invalid divisor")
24
+
25
+ if len(dividend) < len(divisor):
26
+ return [tree_form("d_0")], [item.copy_tree() for item in dividend]
27
+
28
+ # Calculate degrees
29
+ deg_p = len(dividend) - 1
30
+ deg_q = len(divisor) - 1
31
+ deg_quot = deg_p - deg_q
32
+
33
+ # Initialize quotient (highest degree first)
34
+ quotient = [tree_form("d_0")] * (deg_quot + 1)
35
+
36
+ # Working dividend - keep original structure
37
+ working_dividend = [item.copy_tree() for item in dividend]
38
+
39
+ # Long division - align by current leading terms
40
+ for k in range(deg_quot, -1, -1):
41
+ # Remove leading zeros from working dividend
42
+ while len(working_dividend) > 1 and simplify(working_dividend[0]) == 0:
43
+ working_dividend.pop(0)
44
+
45
+ if len(working_dividend) == 0 or simplify(working_dividend[0]) == 0:
46
+ continue
47
+
48
+ # Calculate quotient term for degree k
49
+ leading_ratio = simplify(working_dividend[0] / divisor[0])
50
+ quotient[k] = leading_ratio
51
+
52
+ # Subtract leading_ratio * divisor (aligned at leading terms)
53
+ new_dividend = []
54
+ for i in range(max(len(working_dividend), len(divisor))):
55
+ dividend_term = working_dividend[i] if i < len(working_dividend) else tree_form("d_0")
56
+ divisor_term = simplify(leading_ratio * divisor[i]) if i < len(divisor) else tree_form("d_0")
57
+ result = simplify(dividend_term - divisor_term)
58
+ new_dividend.append(result)
59
+
60
+ working_dividend = new_dividend
61
+
62
+ # Remainder is terms with degree < deg_q (last deg_q terms of final dividend)
63
+ remainder = working_dividend[-(deg_q):] if len(working_dividend) > deg_q else working_dividend
64
+ while len(remainder) > 1 and simplify(remainder[0]) == 0:
65
+ remainder.pop(0)
66
+ if not remainder:
67
+ remainder = [tree_form("d_0")]
68
+
69
+ # Clean quotient trailing zeros
70
+ while len(quotient) > 1 and simplify(quotient[-1]) == 0:
71
+ quotient.pop()
72
+
73
+ return quotient, remainder
74
+
75
+ def unpoly(eq, var):
76
+ eq = eq[::-1]
77
+ eq = [simplify(item) for item in eq]
78
+ eq2 = copy.deepcopy([eq[i]*tree_form(var)**tree_form("d_"+str(i)) if i != 0 else eq[i] for i in range(len(eq))])
79
+ return summation(eq2)
80
+
81
+ def longdiv(p, q, p_min=0, q_min=0):
82
+ p, q = simplify(p), simplify(q)
83
+
84
+ var = set(vlist(p)) & set(vlist(q))
85
+ if len(var) > 0:
86
+ var = list(var)[0]
87
+ p = poly(p, var)
88
+ q = poly(q, var)
89
+ if p is not None and q is not None and len(p)-1>=p_min and len(q)-1>=q_min and len(p)<=len(q):
90
+ a, b = poly_div(p, q)
91
+ return unpoly(a, var), unpoly(b, var)
92
+ return None
93
+ def poly_simplify(eq):
94
+ a, b = num_dem(eq)
95
+ b = simplify(b)
96
+ if b != 1:
97
+ return simplify(poly_simplify(a)/poly_simplify(b))
98
+ for var in vlist(eq):
99
+ n = poly(eq, var, 20)
100
+ if n is not None:
101
+ return simplify(unpoly(n, var))
102
+ return TreeNode(eq.name, [poly_simplify(child) for child in eq.children])
103
+ def enclose_const(eq):
104
+ def req(eq, dic):
105
+ for key in dic.keys():
106
+ eq = replace(eq, dic[key], key)
107
+ return eq
108
+ alloclst = []
109
+ for i in range(0,26):
110
+ if "v_"+str(i) not in vlist(eq):
111
+ alloclst.append(tree_form("v_"+str(i)))
112
+ dic = {}
113
+ def helper(eq):
114
+ nonlocal alloclst, dic
115
+ if frac(eq) is not None:
116
+ return eq
117
+
118
+ if "v_" not in str_form(eq):
119
+ if eq not in dic.keys():
120
+ n = alloclst.pop(0)
121
+ dic[eq] = n
122
+ return dic[eq]
123
+ else:
124
+ if eq.name == "f_pow":
125
+ return TreeNode(eq.name, [helper(eq.children[0]), eq.children[1]])
126
+ return TreeNode(eq.name, [helper(child) for child in eq.children])
127
+ eq= helper(eq)
128
+ return eq, lambda x: req(x, dic)
129
+
130
+ def poly(eq, to_compute, m=10):
131
+ def substitute_val(eq, val, var="v_0"):
132
+ eq = replace(eq, tree_form(var), tree_form("d_"+str(val)))
133
+ return eq
134
+ def inv(eq):
135
+ if eq.name[:2] == "f_" and eq.name[2:] in "ref try integrate subs".split(" "):
136
+ return False
137
+ if eq.name[2:] in ["sin", "cos", "log"] and contain(eq.children[0], tree_form(to_compute)):
138
+ return False
139
+ if eq.name == "f_pow" and contain(eq.children[0], tree_form(to_compute)) and\
140
+ (frac(eq.children[1]) is None or frac(eq.children[1]) < 0 or frac(eq.children[1]).denominator != 1):
141
+ return False
142
+ if eq.name == "f_abs":
143
+ return False
144
+ if any(not inv(child) for child in eq.children):
145
+ return False
146
+ return True
147
+ if not inv(eq):
148
+ return None
149
+ out = []
150
+ eq2 = eq
151
+ for i in range(m):
152
+ out.append(expand(simplify(eq2)))
153
+ eq2 = diff(eq2, to_compute)
154
+ for i in range(len(out)-1,-1,-1):
155
+ if out[i] == tree_form("d_0"):
156
+ out.pop(i)
157
+ else:
158
+ break
159
+ final = []
160
+ for index, item in enumerate(out):
161
+ final.append(substitute_val(item, 0, to_compute)/tree_form("d_"+str(math.factorial(index))))
162
+
163
+ return [expand(simplify(item)) for item in final][::-1]
@@ -58,6 +58,9 @@ def trig0(eq):
58
58
  if a > b:
59
59
  a = 2*b - a
60
60
  return a, b
61
+ if eq.name == "f_arccosec":
62
+ return (1/eq.children[0]).fx("arcsin")
63
+
61
64
  if eq.name == "f_arctan":
62
65
  if eq.children[0].name == "d_0":
63
66
  return tree_form("d_0")
@@ -164,52 +167,61 @@ def _trig1(equation):
164
167
  return TreeNode(equation.name, [_trig1(child) for child in equation.children])
165
168
  def trig1(eq):
166
169
  return simplify(_trig1(noneg_pow(eq)))
167
-
168
- def trig4(eq, numer=True):
169
- if eq.name == "f_sin":
170
- if eq.children[0].name == "f_add" and len(eq.children[0].children)>=2:
171
- r = len(eq.children[0].children)%2
172
- a, b = TreeNode("f_add", eq.children[0].children[:round((len(eq.children[0].children)-r)/2)]),\
173
- TreeNode("f_add", eq.children[0].children[round((len(eq.children[0].children)-r)/2):])
174
- if len(a.children)==1:
175
- a=a.children[0]
176
- if len(b.children)==1:
177
- b=b.children[0]
178
- return a.fx("sin")*b.fx("cos") + a.fx("cos")*b.fx("sin")
179
- if eq.children[0].name == "f_arccos":
180
- a = eq.children[0].children[0]
181
- return (1-a**2)**(tree_form("d_2")**-1)
182
- if eq.children[0].name == "f_arctan":
183
- a = eq.children[0].children[0]
184
- return a/(1+a**2)**(tree_form("d_2")**-1)
185
- if eq.name == "f_pow" and numer:
186
- if eq.children[0].name == "f_cos":
187
- a = eq.children[0].children[0]
188
- if frac(eq.children[1]) == 2:
189
- return 1 - a.fx("sin")**2
190
- if eq.children[0].name == "f_sin":
191
- a = eq.children[0].children[0]
192
- if frac(eq.children[1]) == 2:
193
- return 1 - a.fx("cos")**2
194
- if eq.name == "f_cos":
195
- if eq.children[0].name == "f_add" and len(eq.children[0].children)>=2:
196
- r = len(eq.children[0].children)%2
197
- a, b = TreeNode("f_add", eq.children[0].children[:round((len(eq.children[0].children)-r)/2)]),\
198
- TreeNode("f_add", eq.children[0].children[round((len(eq.children[0].children)-r)/2):])
199
- if len(a.children)==1:
200
- a=a.children[0]
201
- if len(b.children)==1:
202
- b=b.children[0]
203
- return a.fx("cos")*b.fx("cos") - a.fx("sin")*b.fx("sin")
204
- if eq.children[0].name == "f_arcsin":
205
- a = eq.children[0].children[0]
206
- return (1-a**2)**(tree_form("d_2")**-1)
207
- if eq.children[0].name == "f_arctan":
208
- a = eq.children[0].children[0]
209
- return tree_form("d_1")/(1+a**2)**(tree_form("d_2")**-1)
210
-
211
- return TreeNode(eq.name, [trig4(child, False) if not numer or (eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]) < 0) else trig4(child, True) for child in eq.children])
212
-
170
+ def trig4(eq):
171
+ done = False
172
+ def _trig4(eq, numer=True, chance="sin"):
173
+ nonlocal done
174
+ if eq.name == "f_sin":
175
+ if eq.children[0].name == "f_add" and len(eq.children[0].children)>=2:
176
+ r = len(eq.children[0].children)%2
177
+ a, b = TreeNode("f_add", eq.children[0].children[:round((len(eq.children[0].children)-r)/2)]),\
178
+ TreeNode("f_add", eq.children[0].children[round((len(eq.children[0].children)-r)/2):])
179
+ if len(a.children)==1:
180
+ a=a.children[0]
181
+ if len(b.children)==1:
182
+ b=b.children[0]
183
+ return a.fx("sin")*b.fx("cos") + a.fx("cos")*b.fx("sin")
184
+ if eq.children[0].name == "f_arccos":
185
+ a = eq.children[0].children[0]
186
+ return (1-a**2)**(tree_form("d_2")**-1)
187
+ if eq.children[0].name == "f_arctan":
188
+ a = eq.children[0].children[0]
189
+ return a/(1+a**2)**(tree_form("d_2")**-1)
190
+ if eq.name == "f_pow" and numer:
191
+ if eq.children[0].name == "f_cos" and chance == "cos":
192
+ a = eq.children[0].children[0]
193
+ if frac(eq.children[1]) == 2:
194
+ done = True
195
+ return 1 - a.fx("sin")**2
196
+ if eq.children[0].name == "f_sin" and chance == "cos":
197
+ a = eq.children[0].children[0]
198
+ if frac(eq.children[1]) == 2:
199
+ done = True
200
+ return 1 - a.fx("cos")**2
201
+ if eq.name == "f_cos":
202
+ if eq.children[0].name == "f_add" and len(eq.children[0].children)>=2:
203
+ r = len(eq.children[0].children)%2
204
+ a, b = TreeNode("f_add", eq.children[0].children[:round((len(eq.children[0].children)-r)/2)]),\
205
+ TreeNode("f_add", eq.children[0].children[round((len(eq.children[0].children)-r)/2):])
206
+ if len(a.children)==1:
207
+ a=a.children[0]
208
+ if len(b.children)==1:
209
+ b=b.children[0]
210
+ return a.fx("cos")*b.fx("cos") - a.fx("sin")*b.fx("sin")
211
+ if eq.children[0].name == "f_arcsin":
212
+ a = eq.children[0].children[0]
213
+ return (1-a**2)**(tree_form("d_2")**-1)
214
+ if eq.children[0].name == "f_arctan":
215
+ a = eq.children[0].children[0]
216
+ return tree_form("d_1")/(1+a**2)**(tree_form("d_2")**-1)
217
+
218
+ return TreeNode(eq.name, [_trig4(child, False, chance) if eq.name != "f_add" and\
219
+ (not numer or (eq.name == "f_pow" and frac(eq.children[1]) is not None and frac(eq.children[1]) < 0))\
220
+ else _trig4(child, True, chance) for child in eq.children])
221
+ eq= _trig4(eq)
222
+ if not done:
223
+ eq = _trig4(eq,"cos")
224
+ return eq
213
225
  def trig2(eq):
214
226
  # Base case: if not an addition, recurse into children
215
227
  if eq.name != "f_add":
@@ -245,4 +257,3 @@ def trig2(eq):
245
257
 
246
258
  # If no sin/cos pairs found, just recurse on children
247
259
  return TreeNode(eq.name, [trig2(child) for child in eq.children])
248
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mathai
3
- Version: 0.4.6
3
+ Version: 0.4.8
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
@@ -16,6 +16,9 @@ Dynamic: requires-python
16
16
  Dynamic: summary
17
17
 
18
18
  # Math AI Documentation
19
+ ## Source
20
+ Github repository of the code
21
+ https://github.com/infinity390/mathai4
19
22
 
20
23
  ## Philosophy
21
24
  I think it is a big realization in computer science and programming to realize that computers can solve mathematics.
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="mathai",
5
- version="0.4.6",
5
+ version="0.4.8",
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,62 +0,0 @@
1
- from .diff import diff
2
- from .expand import expand
3
- from .simplify import simplify
4
- from .base import *
5
- import math
6
-
7
- def enclose_const(eq):
8
- def req(eq, dic):
9
- for key in dic.keys():
10
- eq = replace(eq, dic[key], key)
11
- return eq
12
- alloclst = []
13
- for i in range(0,26):
14
- if "v_"+str(i) not in vlist(eq):
15
- alloclst.append(tree_form("v_"+str(i)))
16
- dic = {}
17
- def helper(eq):
18
- nonlocal alloclst, dic
19
- if frac(eq) is not None:
20
- return eq
21
-
22
- if "v_" not in str_form(eq):
23
- if eq not in dic.keys():
24
- n = alloclst.pop(0)
25
- dic[eq] = n
26
- return dic[eq]
27
- else:
28
- if eq.name == "f_pow":
29
- return TreeNode(eq.name, [helper(eq.children[0]), eq.children[1]])
30
- return TreeNode(eq.name, [helper(child) for child in eq.children])
31
- eq= helper(eq)
32
- return eq, lambda x: req(x, dic)
33
-
34
- def poly(eq, to_compute):
35
- def substitute_val(eq, val, var="v_0"):
36
- eq = replace(eq, tree_form(var), tree_form("d_"+str(val)))
37
- return eq
38
- def inv(eq):
39
- if eq.name == "f_pow" and "v_" in str_form(eq.children[0]) and eq.children[1] == tree_form("d_-1"):
40
- return False
41
- if eq.name == "f_abs":
42
- return False
43
- if any(not inv(child) for child in eq.children):
44
- return False
45
- return True
46
- if not inv(eq):
47
- return None
48
- out = []
49
- eq2 = eq
50
- for i in range(10):
51
- out.append(expand(simplify(eq2)))
52
- eq2 = diff(eq2, to_compute)
53
- for i in range(len(out)-1,-1,-1):
54
- if out[i] == tree_form("d_0"):
55
- out.pop(i)
56
- else:
57
- break
58
- final = []
59
- for index, item in enumerate(out):
60
- final.append(substitute_val(item, 0, to_compute)/tree_form("d_"+str(math.factorial(index))))
61
-
62
- return [expand(simplify(item)) for item in final][::-1]
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