Limit(((n + 1) + 1) / (((n + 1) + 2) * factorial(n + 1)) *
(n + 2) * factorial(n) / (n + 1), n, oo).doit()
Limit((n + 2)**2*factorial(n)/((n + 1)*(n + 3)*factorial(n + 1)), n, oo).doit()
Result is 1.
but correct result is 0.
If the factorials can be cancelled to get
(n + 2)**2/((n + 1)*(n + 3)*(n + 1)) the result will be correct (clearly, it should be zero seeing it on that form), so that is a hint for solving it. Either add simplification for factorials (will be useful in general) and/or try to figure out the issue with Limits with factorials.
A little more simplified.
Limit(n * factorial(n) / (n * factorial(n)), n, oo).doit() # 0 ok
Limit(n * factorial(n) / (n * factorial(n + 1)), n, oo).doit() # 0 ok
Limit((n + 1) * factorial(n) / (n * factorial(n)), n, oo).doit() # 1 ok
Limit((n + 1) * factorial(n) / (n * factorial(n + 1)), n, oo).doit() # 1 wrong
Running gammasimp on the expression before Limit seems to solve it. Maybe one should do that in Limit when the expression contains factorial or gamma (or RisingFactorial, FallingFactorial, uppergamma, lowergamma, ...)?
Fix in #17434
This issue is related to #17463 . Both factorial and gamma functions do not have the _eval_as_leading_term() method. Hence these functions use the generic method and the return value is not correct.
In the previous cases, the factorials are written as gamma function and then the routine as_leading_term() is called in the evaluation of the limit. The return value is wrong and so the final result. To me the following piece of code in gamma_functions.py solves the issue.
def _eval_as_leading_term(self, x):
from sympy import Order
arg = self.args[0]
arg_1 = arg.as_leading_term(x)
if Order(x, x).contains(arg_1):
return None
if Order(1, x).contains(arg_1):
return self.func(arg_1)
return self.func(arg)
The final line, i.e. return self.func(arg), ideally should be None. See #17463 .