This summer I had plenty of time during COVID-19 lockdown and I was looking at SymPy Gamma.
SymPy Gamma is a web application that executes mathematical expressions via natural language input from the user, after parsing them as SymPy expressions it displays the result with additional related computations. It is inspired from the idea of WolframAlpha which is based on the commercial Computer Algebra System named “Mathematica”.
I have always been impressed by it ever since I first found about it. While playing with it during this summer, I realised that it runs on Google App Engine’s Python 2.7 runtime. It is powered by SymPy, an open source computer algebra system.
Despite being widely used around the world (about ~14K users everyday, as seen from Google Analytics), there hasn’t been a lot of development in the past 5 years. Due to this the current infrastructure was stuck on Google App Engine’s Python 2 runtime which obviously does not support Python 3.
This also prevented it to use the latest version of SymPy. The SymPy version (~0.7.6) it was using was last updated 6 years ago. This made SymPy Gamma in urgent need for upgradation. At the time of writing this blog, SymPy Gamma is running on Google App Engine’s latest runtime and latest version of SymPy.
It was a fun project and was interesting to see how Google cloud offering has evolved from Google App Engine to Google Cloud Platform. The old App engine did seem like a minimal cloud offering launched by Google in an attempt to ship something early and quickly. It reminded me of my first cloud project in college (dturmscrap), which I deployed to Google App Engine, back in 2015.
I used Github projects to track the whole project, all the work done for this can be seen here.
Here is a summary of what was achieved:
PR 135: Migrating Django to a slightly higher version, this was the first blood just to make sure everything was working. I upgraded it to the latest version of Django that was supported on Python 2 runtime. This also exposed the broken CI, which was fixed in this.
PR 137: This upgraded the CI infrastructure to use Google Cloud SDK for deployment, the previous method was discontinued.
PR 140: Upgrading the Database backend to use Cloud NDB instead of the legacy App Engine NDB.
PR 148: Since we change the database backend, we needed something for testing locally, this was done by using Google Cloud Datastore emulator locally.
PR 149: The installation and setup of the project was quite a challenge. Installing and keeping track of the versions of a number of application was non-trivial. This Pull request dockerized the project and made the development setup trivial and it all boiled down to just one command.
PR 152: The login feature was previously implemented using the user API of the Google App Engine’s Python2 runtime, which was not available in Python 3 runtime. We removed the login feature as it was not used by many and was too much effort to setup OAuth for login.
PR 154: We then made the migration to Python 3.7 runtime and removed submodules
and introduced a
requirements.txt for installing dependencies.
PR 159: The above change made it possible to upgrade SymPy to latest version, which was 1.6 at that time.
PR 165: The last piece of the puzzle was upgrading Django itself, so we upgraded it to the latest version, which was Django 3.0.8.
Thanks to Google for properly documenting the process, which made the transition much easier.
This report summarizes the work done in my GSoC 2020 project, Implementation of Vector Integration with SymPy. Blog posts with step by step development of the project are available at friyaz.github.io.
I am Faisal Riyaz and I have completed my third year of B.Tech in Computer Engineering student from Aligarh Muslim University.
The goal of the project is to add functions and class structure to support the integration of scalar and vector fields over curves, surfaces, and volumes. My mentors were Francesco Bonazzi (Primary) and Divyanshu Thakur.
Here is a list of PRs which were opened during the span of GSoC:
(Merged) #19472: Adds
ParametricRegion class to represent parametrically defined regions.
(Merged) #19539: Adds
ParametricIntegral class to represent integral of scalar or vector field over a parametrically defined region.
(Merged) #19580: Modified API of
(Merged) #19650: Added support to integrate over objects of geometry module.
(Merged) #19681: Added
ImplicitRegion class to represent implicitly defined regions.
(Megred) #19807: Implemented the algorithm for rational parametrization of conics.
(Merged) #20000: Added API of newly added classes to sympy’s documentation.
(Open) #19883: Allow
vector_integrate to handle
(Open) #20021: Add usage examples.
We had an important discussion regarding our initial approach and possible problems on issue #19320
ParametricRegion class is used to represent a parametric region in space.
>>> from sympy.vector import CoordSys3D, ParametricRegion, vector_integrate >>> from sympy.abc import r, theta, phi, t, x, y, z >>> from sympy import pi, sin, cos, Eq >>> C = CoordSys3D('C') >>> circle = ParametricRegion((4*cos(theta), 4*sin(theta)), (theta, 0, 2*pi)) >>> disc = ParametricRegion((r*cos(theta), r*sin(theta)), (r, 0, 4), (theta, 0, 2*pi)) >>> box = ParametricRegion((x, y, z), (x, 0, 1), (y, -1, 1), (z, 0, 2)) >>> cone = ParametricRegion((r*cos(theta), r*sin(theta), r), (theta, 0, 2*pi), (r, 0, 3)) >>> vector_integrate(1, circle) 8*pi >>> vector_integrate(C.x*C.x - 8*C.y*C.x, disc) 64*pi >>> vector_integrate(C.i + C.j, box) (Integral(1, (x, 0, 1), (y, -1, 1), (z, 0, 2)))*C.i + (Integral(1, (x, 0, 1), (y, -1, 1), (z, 0, 2)))*C.j >>> _.doit() 4*C.i + 4*C.j >>> vector_integrate(C.x*C.i - C.z*C.j, cone) -9*pi
Many regions like circle are commonly encountered in problems of vector calculus. the geometry module of SymPy already had classes for some of these regions. The function
parametric_region_list was added to determine the parametric representation of such classes.
vector_integrate can directly integrate objects of Point, Curve, Ellipse, Segment and Polygon class of
>>> from sympy.geometry import Point, Segment, Polygon, Segment >>> s = Segment(Point(4, -1, 9), Point(1, 5, 7)) >>> triangle = Polygon((0, 0), (1, 0), (1, 1)) >>> circle2 = Circle(Point(-2, 3), 6) >>> vector_integrate(-6, s) -42 >>> vector_integrate(C.x*C.y, circle2) -72*pi >>> vector_integrate(C.y*C.z*C.i + C.x*C.x*C.k, triangle) -C.z/2
In many cases, it is difficult to determine the parametric representation of a region. Instead, the region is defined using its implicit equation. To represent implicitly defined regions, we implemented the
But to integrate over a region, we need to determine its parametric representation. the
rationl_parametrization method was added to
>>> from sympy.vector import ImplicitRegion >>> circle3 = ImplicitRegion((x, y), (x-4)**2 + (y+3)**2 - 16) >>> parabola = ImplicitRegion((x, y), (y - 1)**2 - 4*(x + 6)) >>> ellipse = ImplicitRegion((x, y), (x**2/4 + y**2/16 - 1)) >>> rect_hyperbola = ImplicitRegion((x, y), x*y - 1) >>> sphere = ImplicitRegion((x, y, z), Eq(x**2 + y**2 + z**2, 2*x)) >>> circle3.rational_parametrization() (8*t/(t**2 + 1) + 4, 8*t**2/(t**2 + 1) - 7) >>> parabola.rational_parametrization() (-6 + 4/t**2, 1 + 4/t) >>> rect_hyperbola.rational_parametrization(t) (-1 + (t + 1)/t, t) >>> ellipse.rational_parametrization() (t/(2*(t**2/16 + 1/4)), t**2/(2*(t**2/16 + 1/4)) - 4) >>> sphere.rational_parametrization() (2/(s**2 + t**2 + 1), 2*s/(s**2 + t**2 + 1), 2*t/(s**2 + t**2 + 1))
After PR #19883 gets merged,
vector_integrate can directly work upon
In vector calculus, many regions cannot be defined using a single implicit equation. Instead, inequality or a combination of the implicit equation and conditional equations is required. For Example, a disc can only be represented using an inequality
ImplicitRegion(x**2 + y**2 < 9) and a semicircle can be represented as
ImplicitRegion(x**2 + y**2 -4) & (y < 0)). Support for such implicit regions needs to be added.
The parametrization obtained using the
rational_parametrization method in most cases is a large expression. SymPy’s
Integral is unable to work over such expressions. It takes too long and often does not returns a result. We need to either simplify the parametric equations obtained or fix Integral to handle them.
Adding the support to plot objects of
This summer has been a great learning experience. Writing a functionality, testing, debugging it has given me good experience in test-driven development. I think I realized many of the goals that I described in my proposal, though there were some major differences in the plan and actual implementation. Personally, I hoped I could have done better. I could not work much on the project during the last phase due to the start of the academic year.
I would like to thank Francesco for his valuable suggestions and being readily available for discussions. He was always very friendly and helpful. I would love to work more with him. S.Y Lee also provided useful suggestions.
Special thanks to Johann Mitteramskogler, Professor Sonia Perez Diaz, and Professor Sonia L.Rueda. They personally helped me in finding the algorithm for determining the rational parametrization of conics.
SymPy is an amazing project with a great community. I would mostly stick around after the GSoC period as well and continue contributing to SymPy, hopefully, exploring the other modules as well.