Симпатичный левосторонний предел функции знака - PullRequest
0 голосов
/ 06 ноября 2018

Я изучаю библиотеку sympy для python для своих целей обучения Я хотел бы рассчитать следующий лимит:
image
Итак, у меня есть код:

import sympy as sp
x = sp.Symbol('x')
f = sp.sign(sp.cos(sp.pi/x))
sp.limit(f, x, 2, '-')

Но я получаю следующую ошибку:

TypeError                                 Traceback (most recent call last)
<ipython-input-31-56b1fd6b589d> in <module>()
      1 x = sp.Symbol('x')
      2 f = sp.sign(sp.cos(sp.pi/x))
----> 3 sp.limit(f, x, 2, '-')
~\Anaconda3\lib\site-packages\sympy\series\limits.py in limit(e, z, z0, dir)
     47     """
     48 
---> 49     return Limit(e, z, z0, dir).doit(deep=False)
     50 
     51 
~\Anaconda3\lib\site-packages\sympy\series\limits.py in doit(self, **hints)
    178 
    179         try:
--> 180             r = gruntz(e, z, z0, dir)
    181             if r is S.NaN:
    182                 raise PoleError()
~\Anaconda3\lib\site-packages\sympy\series\gruntz.py in gruntz(e, z, z0, dir)
    656         else:
    657             raise NotImplementedError("dir must be '+' or '-'")
--> 658         r = limitinf(e0, z)
    659 
    660     # This is a bit of a heuristic for nice results... we always rewrite
~\Anaconda3\lib\site-packages\sympy\series\gruntz.py in limitinf(e, x)
    426         e = e.subs(x, p)
    427         x = p
--> 428     c0, e0 = mrv_leadterm(e, x)
    429     sig = sign(e0, x)
    430     if sig == 1:
~\Anaconda3\lib\site-packages\sympy\series\gruntz.py in mrv_leadterm(e, x)
    511     w = Dummy("w", real=True, positive=True, finite=True)
    512     f, logw = rewrite(exps, Omega, x, w)
--> 513     series = calculate_series(f, w, logx=logw)
    514     return series.leadterm(w)
    515 
~\Anaconda3\lib\site-packages\sympy\series\gruntz.py in calculate_series(e, x, logx)
    464     from sympy.polys import cancel
    465 
--> 466     for t in e.lseries(x, logx=logx):
    467         t = cancel(t)
    468 
~\Anaconda3\lib\site-packages\sympy\core\expr.py in yield_lseries(s)
   2635             def yield_lseries(s):
   2636                 """Return terms of lseries one at a time."""
-> 2637                 for si in s:
   2638                     if not si.is_Add:
   2639                         yield si
~\Anaconda3\lib\site-packages\sympy\core\expr.py in _eval_lseries(self, x, logx)
   2700         # terms.
   2701         n = 0
-> 2702         series = self._eval_nseries(x, n=n, logx=logx)
   2703         if not series.is_Order:
   2704             if series.is_Add:
~\Anaconda3\lib\site-packages\sympy\core\function.py in _eval_nseries(self, x, n, logx)
    685         cf = Order(arg.as_leading_term(x), x).getn()
    686         if cf != 0:
--> 687             nterms = int(nterms / cf)
    688         for i in range(nterms):
    689             g = self.taylor_term(i, arg, g)
TypeError: unsupported operand type(s) for /: 'int' and 'NoneType'

В чем проблема? Я легко вычислял пределы и не имел такой ошибки прежде. Есть ли способ это исправить? Я не нашел один.

1 Ответ

0 голосов
/ 06 ноября 2018

Это ошибка в расчете лимита; если вы не сталкивались с такими ошибками раньше, это просто означает, что вы не дали SymPy достаточно сложные ограничения. Неаналитические, кусочно определенные функции, такие как abs и sign, доставляют много хлопот алгоритму SymPy, который основан на разложении в ряды. Иногда он управляет правильным ответом, иногда дает неправильный ответ, а иногда вообще не отвечает.

Когда sign(something) не работает, разумно попробовать something/Abs(something), что математически эквивалентно, но может работать лучше (или хуже) в SymPy.

f = sp.cos(sp.pi/x) / sp.Abs(sp.cos(sp.pi/x))
sp.limit(f, x, 2, '-')

не вызывает никаких исключений и быстро возвращает ответ: 1. К сожалению, ответ неверный ...

Если проблему сделать проще, заменив pi/x символом y (который теперь приближается к pi/2 из вправо ), тогда SymPy получит правильный ответ:

y = sp.symbols('y')
f = sp.cos(y) / sp.Abs(sp.cos(y))
sp.limit(f, y, sp.pi/2, '+')  

возвращает -1.

...