GSoC 2020 - Final Report
29 Aug 2020This report summarises the work I have done during GSoC 2020 for SymPy. The links to the PRs are in chronological order. For following the progress made during GSoC, see my blog for the weekly posts.
About Me
I am Sachin Agarwal, a third-year undergraduate student majoring in Computer Science and Engineering from the Indian Institute of Information Technology, Guwahati.
Project Synopsis
My project involved fixing and amending functions related to series expansions and limit evaluation. For further information, my proposal for the project can be referred.
Pull Requests
This section describes the actual work done during the coding period in terms of merged PRs.
Phase 1
-
#19292 : This PR added a condition to
limitinfmethod ofgruntz.pyresolving incorrect limit evaluations. -
#19297 : This PR replaced
xreplace()withsubs()inrewritemethod ofgruntz.pyresolving incorrect limit evaluations. -
#19369 : This PR fixed
_eval_nseriesmethod ofmul.py. -
#19432 : This PR added a functionality to the
doitmethod oflimits.pywhich usesis_meromorphicfor limit evaluations. -
#19461 : This PR corrected the
_eval_as_leading_termmethod oftanandsecfunctions. -
#19508 : This PR fixed
_eval_nseriesmethod ofpower.py. -
#19515 : This PR added
_eval_rewrite_as_factorialand_eval_rewrite_as_gammamethods toclass subfactorial.
Phase 2
-
#19555 : This PR added
cdirparameter to handleseries expansionsonbranch cuts. -
#19646 : This PR rectified the
mrvmethod ofgruntz.pyandcancelmethod ofpolytools.pyresolvingRecursionErrorandTimeoutin limit evaluations. -
#19680 : This PR added
is_Powheuristic tolimits.pyto improve the limit evaluations ofPow objects. -
#19697 : This PR rectified
_eval_rewrite_as_tractablemethod ofclass erf. -
#19716 : This PR added
_singularitiestoLambertWfunction. -
#18696 : This PR fixed errors in assumptions when rewriting
RisingFactorial/FallingFactorialasgammaorfactorial.
Phase 3
-
#19741 : This PR reduced
symbolic multiples of piintrigonometric functions. -
#19916 : This PR added
_eval_nseriesmethod tosinandcos. -
#19963 : This PR added
_eval_is_meromorphicmethod to theclass BesselBase. -
#18656 : This PR added
Raabe's Testto theconcretemodule. -
#19990 : This PR added
_eval_is_meromorphicand_eval_aseriesmethods toclass lowergamma,_eval_is_meromorphicand_eval_rewrite_as_tractablemethods toclass uppergammaand rectified theevalmethod ofclass besselk. -
#20002 : This PR fixed
_eval_nseriesmethod oflog.
Miscellaneous Work
This section contains some of my PRs related to miscellaneous issues.
-
#19447 : This PR added some required testcases to
test_limits.py. -
#19537 : This PR fixed a minor
performanceissue. -
#19604 : This PR fixed
AttributeErrorin limit evaluation.
Reviewed Work
This section contains some of the PRs which were reviewed by me.
Issues Opened
This section contains some of the issues which were opened by me.
- #19670 :
Poly(E**100000000)is slow to create. - #19752 :
gammasimpcan be improved forintegervariables.
Examples
This section describes the bugs fixed and the new features added during GSoC.
Fixed Limit Evaluations
>>> from sympy import limit, limit_seq
>>> n = Symbol('n', positive=True, integer=True)
>>> limit(factorial(n + 1)**(1/(n + 1)) - factorial(n)**(1/n), n, oo)
exp(-1) # Previously produced 0
>>> n = Symbol('n', positive=True, integer=True)
>>> limit(factorial(n)/sqrt(n)*(exp(1)/n)**n, n, oo)
sqrt(2)*sqrt(pi) # Previously produced 0
>>> n = Symbol('n', positive=True, integer=True)
>>> limit(n/(factorial(n)**(1/n)), n, oo)
exp(1) # Previously produced oo
>>> limit(log(exp(3*x) + x)/log(exp(x) + x**100), x, oo)
3 # Previously produced 9
>>> limit((2*exp(3*x)/(exp(2*x) + 1))**(1/x), x, oo)
exp(1) # Previously produced exp(7/3)
>>> limit(sin(x)**15, x, 0, '-')
0 # Previously it hanged
>>> limit(1/x, x, 0, dir="+-")
zoo # Previously raised ValueError
>>> limit(gamma(x)/(gamma(x - 1)*gamma(x + 2)), x, 0)
-1 # Previously it was returned unevaluated
>>> e = (x/2) * (-2*x**3 - 2*(x**3 - 1) * x**2 * digamma(x**3 + 1) + 2*(x**3 - 1) * x**2 * digamma(x**3 + x + 1) + x + 3)
>>> limit(e, x, oo)
1/3 # Previously produced 5/6
>>> a, b, c, x = symbols('a b c x', positive=True)
>>> limit((a + 1)*x - sqrt((a + 1)**2*x**2 + b*x + c), x, oo)
-b/(2*a + 2) # Previously produced nan
>>> limit_seq(subfactorial(n)/factorial(n), n)
1/e # Previously produced 0
>>> limit(x**(2**x*3**(-x)), x, oo)
1 # Previously raised AttributeError
>>> limit(n**(Rational(1, 1e9) - 1), n, oo)
0 # Previously it hanged
>>> limit((1/(log(x)**log(x)))**(1/x), x, oo)
1 # Previously raised RecursionError
>>> e = (2**x*(2 + 2**(-x)*(-2*2**x + x + 2))/(x + 1))**(x + 1)
>>> limit(e, x, oo)
exp(1) # Previously raised RecursionError
>>> e = (log(x, 2)**7 + 10*x*factorial(x) + 5**x) / (factorial(x + 1) + 3*factorial(x) + 10**x)
>>> limit(e, x, oo)
10 # Previously raised RecursionError
>>> limit((x**2000 - (x + 1)**2000) / x**1999, x, oo)
-2000 # Previously it hanged
>>> limit(((x**(x + 1) + (x + 1)**x) / x**(x + 1))**x, x, oo)
exp(exp(1)) # Previously raised RecursionError
>>> limit(Abs(log(x)/x**3), x, oo)
0 # Previously it was returned unevaluted
>>> limit(x*(Abs(log(x)/x**3)/Abs(log(x + 1)/(x + 1)**3) - 1), x, oo)
3 # Previously raised RecursionError
>>> limit((1 - S(1)/2*x)**(3*x), x, oo)
zoo # Previously produced 0
>>> d, t = symbols('d t', positive=True)
>>> limit(erf(1 - t/d), t, oo)
-1 # Previously produced 1
>>> s, x = symbols('s x', real=True)
>>> limit(erf(s*x)/erf(s), s, 0)
x # Previously produced 1
>>> limit(erfc(log(1/x)), x, oo)
2 # Previously produced 0
>>> limit(erf(sqrt(x)-x), x, oo)
-1 # Previously produced 1
>>> a, b = symbols('a b', positive=True)
>>> limit(LambertW(a), a, b)
LambertW(b) # Previously produced b
>>> limit(uppergamma(n, 1) / gamma(n), n, oo)
1 # Previously produced 0
>>> limit(besselk(0, x), x, oo)
0 # Previously produced besselk(0, oo)
Rewrote Mul._eval_nseries()
>>> e = (exp(x) - 1)/x
>>> e.nseries(x, 0, 3)
1 + x/2 + x**2/6 + O(x**3) # Previously produced 1 + x/2 + O(x**2, x)
>>> e = (2/x + 3/x**2)/(1/x + 1/x**2)
>>> e.nseries(x, n=3)
3 - x + x**2 + O(x**3) # Previously produced 3 + O(x)
Rewrote Pow._eval_nseries()
>>> e = (x**2 + x + 1) / (x**3 + x**2)
>>> series(e, x, oo)
x**(-5) - 1/x**4 + x**(-3) + 1/x + O(x**(-6), (x, oo))
# Previously produced x**(-5) + x**(-3) + 1/x + O(x**(-6), (x, oo))
>>> e = (1 - 1/(x/2 - 1/(2*x))**4)**(S(1)/8)
>>> e.series(x, 0, n=17)
1 - 2*x**4 - 8*x**6 - 34*x**8 - 152*x**10 - 714*x**12 - 3472*x**14 - 17318*x**16 + O(x**17)
# Previously produced 1 - 2*x**4 - 8*x**6 - 34*x**8 - 24*x**10 + 118*x**12 - 672*x**14 - 686*x**16 + O(x**17)
Added Series Expansions and Limit evaluations on Branch-Cuts
>>> asin(I*x + I*x**3 + 2)._eval_nseries(x, 3, None, 1)
-asin(2) + pi - sqrt(3)*x/3 + sqrt(3)*I*x**2/9 + O(x**3)
>>> limit(log(I*x - 1), x, 0, '-')
-I*pi
Rectified ff._eval_rewrite_as_gamma() and rf._eval_rewrite_as_gamma()
>>> n = symbols('n', integer=True)
>>> combsimp(RisingFactorial(-10, n))
3628800*(-1)**n/factorial(10 - n) # Previously produced 0
>>> ff(5, y).rewrite(gamma)
120/Gamma(6 - y) # Previously produced 0
Added Raabe’s Test
>>> Sum(factorial(n)/factorial(n + 2), (n, 1, oo)).is_convergent()
True # Previously raised NotImplementedError
>>> Sum((-n + (n**3 + 1)**(S(1)/3))/log(n), (n, 1, oo)).is_convergent()
True # Previously raised NotImplementedError
Rewrote log._eval_nseries()
>>> f = log(x/(1 - x))
>>> f.series(x, 0.491, n=1).removeO()
-0.0360038887560022 # Previously raised ValueError
Future Work
- Refactoring high level functions like
series,nseries,lseriesandaseries. - Add
_eval_is_meromorphicmethod or_singularitiesto as many special functions as possible. - Work can be done to resolve the issues opened by me (listed above).
Conclusion
This summer has been a great learning experience and has helped me get a good exposure of test-driven development. I plan to continue contributing to SymPy and will also try to help the new contributors. I am grateful to my mentors, Kalevi Suominen and Sartaj Singh for reviewing my work, giving me valuable suggestions, and being readily available for discussions.