Simple REST service around SymPy
SymPy is a great library for symbolic mathematics. It aims to become a full-featured computer algebra system (CAS).
This project is a simple REST wrapper around SymPy, which allows calling most (but not all) SymPy functions via HTTP requests.
The service allows:
- Calling any SymPy functions and methods on any math eхpression, parseable with SymPy.
- Getting results in SymPy expression language.
- Generating 2d and 3d plots and returning them in PNG or SVG format.
- Running several additional custom functionality. In particular:
- Solving integrals step by step and providing the step by step solution.
- Checking if two mathematical expressions are equivalent and, if yes telling which one is simpler.
The simplest way to run math-processor is using its docker image
docker run -d -p "80:5000" softaria/math-processor
Please replace 80 with a port where you want the service to run.
There are following endpoints in the math-processor REST service:
- /api/v1/method
- /api/v1/function
- /api/v1/plot
- /api/v1/custom
Below we suppose the server is running at http://localhost:80
URL: http://localhost:80/api/v1/method
Supported HTTP method: POST
Meaning: It calls the python method on the provided SymPy object (expression).
Body: JSON as following:
{
"object":"{Sympy expression to be transformed to SymPy object. We will call method on this object.}"
"method":"{name of python method to be called on the object (e.g. doit)}",
"args":[{an array of arguments to be passed to the method (if any)}],
}
Result: either HTTP code 400 with the error explanation or JSON as following
{
"ok": {"True" or "False"}
"result": {Only exists if ok=True. Contains the execution result}
"error: {Only exists if ok=False. Contains human-readable error description}
"errorCode": {Only exists if ok=False. Contains error code (see below)}
}
Error codes:
- BAD_ARGUMENT - the provided object or some of the provided arguments can't be parsed as SymPy expression.
- METHOD_FAILURE - the call of the method failed.
In contrast to errors described in the response JSON that are useful in runtime, errors with HTTP code 400 mean the calling code must be fixed. In particular, they occur when you do not pass JSON body at all or when the JSON lacks one of its required fields.
Example:
Let's call method doit() on SymPy expression Integral(Mul(Integer(2),Symbol('x')),(Symbol('x'),Integer(0),Integer(1)))
Let's do it with curl
curl -d "@doit.json" -X POST -H "Content-Type: application/json" http://localhost:80/api/v1/method
where doit.json contains following:
{"method":"doit","args":[],"object":"Integral(Mul(Integer(2),Symbol('x')),(Symbol('x'),Integer(0),Integer(1)))"}
The result will be:
{"ok": true, "result": "Integer(1)"}
You can try it yourself without installing the math-processor. Just use one installed at https://math-processor.math-editor.com
You are allowed to run any method, supported by SymPy.
For example, here is JSON for rewriting tan(x) via sinuses.
{
"method": "rewrite",
"object":"tan(x)",
"args": [
"sin"
]
}
It is the equivalent of typing in python: Tan(x).rewrite(sin)
The result will be:
{
"ok": true,
"result": "Mul(Integer(2), Pow(sin(Symbol('x')), Integer(2)), Pow(sin(Mul(Integer(2), Symbol('x'))), Integer(-1)))"
}
URL: http://localhost:80/api/v1/function
Supported HTTP method: POST
Meaning: It calls a function defined in 'sympy' module with the provided arguments (SymPy expressions)
Body: JSON as following:
{
"method":"{name of a function from 'sympy' python module to call}",
"args":[{an array of arguments to be passed to the function}],
"params":{{optional object with key-value pairs to pass to the function as a last argument}}
}
While 'method' and 'args' are self-explanatory, 'params' needs comments: Sympy methods often has the last arguments for passing options. E.g. simplify has such optional parameters as
ratio=1.7, measure=<function count_ops>, rational=False, inverse=False, doit=True
Params is here to pass that kind of parameters. For example to pass doit=False, use
{ "doit":false}
as params.
Result: either HTTP code 400 with the error explanation or JSON as following
{
"ok": {"True" or "False"}
"result": {Only exists if ok=True. Contains the execution result}
"error: {Only exists if ok=False. Contains human readable error description}
"errorCode": {Only exists if ok=False. Contains error code (see below)}
}
Error codes:
- BAD_ARGUMENT - some of the provided arguments can't be parsed as SymPy expression.
- METHOD_FAILURE - the call of the function failed.
Example:
Let's call simplify(Pow(sin(x),2) + Pow(cos(x),2))
curl -d "@simplify.json" -X POST -H "Content-Type: application/json" http://localhost:80/api/v1/function
simplify.json:
{
"method": "simplify",
"args": [
"Pow(sin(x),2) + Pow(cos(x),2)"
]
}
The result:
{"ok": true, "result": "Integer(1)"}
URL: http://localhost:80/api/v1/plot
Supported HTTP method: GET
Meaning: It uses SymPy plotting and matplotlib to generate 2d, 3d and parametric plots.
Query parameters:
- method
- args
- params
- checkOnly
- format
It specifies what type of plot you want to get. In fact, it is the name of sympy plotting functions:
- plot
- plot_parametric
- plot3d
- plot3d_parametric_line
- plot3d_parametric_surface
The functions are described here: https://docs.sympy.org/latest/modules/plotting.html
Ags is a JSON array of SymPy expressions to plot. We have an array here as some of the plotting functions above require more than one mathematical function.
Optional parameter.
Params are plain key-value pairs formatted as JSON. They are parsed and passed as the kwargs to corresponding SymPy plotting function (for details: https://docs.sympy.org/latest/modules/plotting.html). Its goal to pass all the additional parameters such as required plot size or its resolution.
Optional parameter.
If present, the math-processor only checks if the passed arguments are valid and returns JSON formatted answer instead of the plot itself. Useful when your code wants to know if the plot was generated perfectly or if the plot image is broken because of error.
If passed, the result will be JSON as following:
{
"ok": {"true" or "false"}
"result": {Only exists if ok=true. Contains the execution result}
"error: {Only exists if ok=false. Contains human readable error description}
"errorCode": {Only exists if ok=False. Contains error code (see below)}
}
Where error codes are:
- BAD_ARGUMENT - at least one of the arguments can't be parsed
- BAD_METHOD - 'method' parameter does not equal to any of the supported values listed above
- METHOD_FAILURE - internal error occurs when the sympy plotting method was called
Optional parameter.
If omitted or not equal to 'svg' then png format is used. If equal to 'svg' the result is generated in SVG format.
https://math-processor.math-editor.com/api/v1/plot?method=plot3d&args=["cos(Add(Abs(Symbol('x'))%2CAbs(Symbol('y'))))"]
the result is
Besides calling SymPy built-in functions and methods, the math-processor has several manually coded functionality its authors found usable. For now it is:
- Ability to get step by step solution for integrals
- Ability to check if 2 expressions are equivalent
- Mirror method (see below for details)
URL: http://localhost:80/api/v1/custom
Supported HTTP method: POST
Body: JSON as following:
{
"method": "{name of custom method to call}",
"args": [ {JSON array of expressions to pass to the custom method} ]
}
Where the method is one of the following:
- integral_steps - calculate integral step by step and return the step by step solution
- equiv - check if two expressions are equivalent
- mirror - parse the provided expression and return its canonical SymPy form
If the custom method ends with error it returns following JSON:
The negative result is:
{
"ok": "false"
"error: {Contains human readable error description.}
"errorCode": {Contains error code (see below).}
}
Error codes are:
- BAD_ARGUMENT - can't parse at least one of the passed expressions
- BAD_METHOD - no method for given name found
- METHOD_FAILURE - internal error occurred while executing the method
curl -d "@integrate.json" -X POST -H "Content-Type: application/json" http://localhost:80/api/v1/custom
where integrate.json is, for example:
{
"method": "integral_steps",
"args": [
"exp(x) / (1 + exp(2 * x))",
"Symbol('x')"
]
}
Look here for the result explanation.
curl -d "@equiv.json" -X POST -H "Content-Type: application/json" http://localhost:80/api/v1/custom
where equiv.json could be (note it must contain exactly two arguments):
{
"method": "equiv",
"args": [
"Pow(sin(x),2) + Pow(cos(x),2)",
"1"
]
}
The positive result is:
{
"ok": true,
"result":
{
"eq": "{eqivalency type}",
"si": "{which expression is simpler}"
}
}
where equivalency type is one of:
- identical - expressions are literally identical
- equiv - expressions become equal when you do some algebra transformation
- equivCalc - expression become equal only if you apply calculus transformation (like integrating, differentiating or calculating limit)
- different - expressions are not equivalent
the value of "si" could be one of the following:
- first - you have to simplify the second expression more than the first in order to make them identical.
- second - you have to simplify the first expression more than the second in order to make them identical.
- none - returned when the expressions are identical.
- unknown - you have to simplify both expressions to make them identical and these simplifications are both algebraic or both calulus.
curl -d "@mirror.json" -X POST -H "Content-Type: application/json" http://localhost:80/api/v1/custom
where mirror.json could be:
{
"method": "mirror",
"args": [
"Pow(sin(x),2) + Pow(cos(x),2)"
]
}
It returns canonical SymPy form of the given expression. Or reports an error.
E.g. for the exression given above the answer is:
{"ok": true, "result": "Add(Pow(sin(Symbol('x')), Integer(2)), Pow(cos(Symbol('x')), Integer(2)))"}
The math-processor is integrated with our math-editor. So, you can try its calculating and plotting functionality here