Symbolic Integrals
Symbolics.jl provides a the Integral
operator for defining integrals. These can be used with various functionalities in order to represent integro-differential equations and as a representation for symbolic solving of integrals.
This area is currently under heavy development. More solvers will be available in the near future.
Defining Symbolic Integrals
Note that integration domains are defined using DomainSets.jl.
Symbolics.Integral
— TypeIntegral(domain)
Defines an Integral operator I(ex) which represents the integral of I
of the expression ex
over the domain
. Note that the domain
must be a Symbolics.VarDomainPairing
where the chosen variable is the variable being integrated over, i.e. Integral(x in domain)
means that I
is the integral operator with respect to dx
.
Examples
I1 = Integral(x in ClosedInterval(1, 5))
I2 = Integral(x in ClosedInterval(1, 5))
@variables a b
I = Integral(x in ClosedInterval(a, b))
@test isequal(I(0), 0)
@test isequal(I(2), 2*(b -a))
Solving Symbolic Integrals
Symbolics.jl currently has the following options for solving integrals symbolically:
Package | Method | Description | Pros | Cons |
---|---|---|---|---|
SymbolicIntegration.jl | Risch Algorithm | Implements theoretical Risch algorithm for elementary functions | Mathematically rigorous, returns exact symbolic results, handles rational functions and transcendental functions (exp, log, trig) | Still in early development, unstable, limited to specific function classes, no support for algebraic functions |
SymbolicIntegration.jl | Rule-Based Method | Applies over 3,400 integration rules systematically | Handles non-integer powers, supports multiple symbolic variables, more flexible than pure Risch | Rule-dependent success, no theoretical completeness guarantee, limited by predefined rule set |
SymbolicNumericIntegration.jl | Symbolic-Numeric Hybrid | Uses numeric integrators with symbolic regression machine learning methods | Can solve some hard integrals very fast and easily, works differently from pure symbolic methods | Can be unreliable in easy cases, will give floats (0.5) instead of rational values (1//2), precision loss |
SymPy's Integrate | Hybrid Methods | Uses SymPy (through SymPy.jl) to integrate the expression | Reasonably robust and tested solution, mature implementation | Extremely slow, Python overhead |
SymbolicIntegration.jl
SymbolicIntegration.jl provides pure symbolic integration using multiple algorithmic approaches. Unlike numerical methods, it returns exact symbolic results with rational coefficients (e.g., 1//2
instead of 0.5
). The package implements a flexible framework for symbolic integration that uses Julia's multiple dispatch to select appropriate algorithms for different types of integrands.
The package offers two main integration methods:
Risch Algorithm Method
The RischMethod
implements the theoretical Risch algorithm for integrating:
- Polynomial functions
- Rational functions
- Exponential functions
- Logarithmic functions
- Trigonometric functions
- Combinations of the above
This method is mathematically rigorous and provides guaranteed results when an elementary antiderivative exists. However, it is still under development and may not handle all cases robustly.
Rule-Based Method
The rule-based approach systematically applies over 3,400 integration rules to solve integrals:
- Handles non-integer powers and algebraic functions
- Supports more complex integrations than pure Risch
- Can handle multiple symbolic variables
- More flexible but depends on the predefined rule set
The package automatically tries the Risch algorithm first, then falls back to rule-based methods if needed.
For using SymbolicIntegration.jl, see the SymbolicIntegration.jl repository for more details. Quick examples:
using Symbolics
using SymbolicIntegration
@variables x
# Basic integrations (automatic method selection)
integrate(x^2, x) # Returns (1//3)*(x^3)
integrate(1/x, x) # Returns log(x)
integrate(exp(x), x) # Returns exp(x)
integrate(1/(x^2 + 1), x) # Returns atan(x)
# Rational function with complex roots (typically uses Risch)
f = (x^3 + x^2 + x + 2)/(x^4 + 3*x^2 + 2)
integrate(f, x) # Returns (1//2)*log(2 + x^2) + atan(x)
# Nested transcendental functions (uses Risch)
integrate(1/(x*log(x)), x) # Returns log(log(x))
# Explicit Risch method selection
integrate(sin(x)*cos(x), x, RischMethod())
# Configurable Risch method
risch = RischMethod(use_algebraic_closure=true, catch_errors=false)
integrate(exp(x)/(1 + exp(x)), x, risch)
# Rule-based method for cases not handled by Risch
integrate(x^(1/2), x) # Uses rule-based method for non-integer powers
integrate(sqrt(x + 1), x) # Handles algebraic functions via rules
SymbolicNumericIntegration.jl
SymbolicNumericIntegration.jl is a package for solving symbolic integrals using numerical methods. Specifically, it mixes numerical integration with machine learning symbolic regression in order to discover the basis for the integrals solution, for which it then finds the coefficients and uses differentiation to prove the correctness of the result. While this technique is unusual and new, see the paper for details, it has the advantage of working very differently from the purely symbolic methods, and thus the problems which it finds hard can be entirely different from ones which the purely symbolic methods find hard. That is, while purely symbolic methods have difficulty depending on the complexity of the expression, this method has difficulty depending on the uniqueness of the numerical solution of the expression, and there are many complex expressions which have a very distinct solution behavior and thus can be easy to solve through this method.
One major downside to this method is that, because it works numerically, there can be precision loss in the coefficients. Thus the returned solution may have 0.5
instead of 1//2
.
For using SymbolicNumericIntegration.jl, see the SymbolicNumericIntegration.jl documentation for more details. A quick example is:
using Symbolics
using SymbolicNumericIntegration
@variables x a b
integrate(3x^3 + 2x - 5)
# (x^2 + (3 // 4) * (x^4) - (5 // 1) * x, 0, 0)
integrate(exp(a * x), x; symbolic = true)
# (exp(a * x) / a, 0, 0)
integrate(sin(a * x) * cos(b * x), x; symbolic = true, detailed = false)
# (-a * cos(a * x) * cos(b * x) - b * sin(a * x) * sin(b * x)) / (a^2 - (b^2))
SymPy
The function sympy_integrate
allows one to call SymPy's integration functionality. While it's generally slow, if you leave your computer on for long enough it can solve some difficult expressions.
Symbolics.sympy_integrate
— Functionsympy_integrate(expr, var)
Computes indefinite integral of expr w.r.t. var using SymPy.
Arguments
expr
: Symbolics expression.var
: Symbolics variable.
Returns
Symbolics integral.
Example
@variables x
expr = x^2
result = sympy_integrate(expr, x)