|
1 | 1 | # SymbolicNumericIntegration.jl |
| 2 | +**SymbolicNumericIntegration.jl** is a hybrid symbolic/numerical integration package that works on the [Julia Symbolics](https://github.com/JuliaSymbolics/Symbolics.jl) expressions. |
2 | 3 |
|
3 | | -Documentation for SymbolicNumericIntegration.jl |
| 4 | +**SymbolicNumericIntegration.jl** uses a randomized algorithm based on a hybrid of the *method of undetermined coefficients* and *sparse regression* and is able to solve a large subset of basic standard integrals (polynomials, exponential/logarithmic, trigonometric and hyperbolic, inverse trigonometric and hyperbolic, rational and square root). |
| 5 | +The basis of how it works and the theory of integration using the Symbolic-Numeric methods refer to [Basis of Symbolic-Numeric Integration](docs/theory.ipynb). |
| 6 | + |
| 7 | +Function `integrate` returns the integral of a univariate expression with *constant* real or complex coefficients. `integrate` returns a tuple with three values. The first one is the solved integral, the second one is the sum of the unsolved terms, and the third value is the residual error. If `integrate` is successful, the unsolved portion is reported as 0. |
| 8 | + |
| 9 | +```julia |
| 10 | +using Symbolics |
| 11 | +using SymbolicNumericIntegration |
| 12 | + |
| 13 | +@variables x |
| 14 | + |
| 15 | +julia> integrate(3x^3 + 2x - 5) |
| 16 | +(x^2 + (3//4)*(x^4) - (5x), 0, 0) |
| 17 | + |
| 18 | +julia> integrate((5 + 2x)^-1) |
| 19 | +((1//2)*log((5//2) + x), 0, 0.0) |
| 20 | + |
| 21 | +julia> integrate(1 / (6 + x^2 - (5x))) |
| 22 | +(log(x - 3) - log(x - 2), 0, 3.339372764128952e-16) |
| 23 | + |
| 24 | +y = integrate(1 / (x^2 - 16)) |
| 25 | +((1//8)*log(x - 4) - ((1//8)*log(4 + x)), 0, 1.546926788028958e-16) |
| 26 | + |
| 27 | +julia> integrate(x^2/(16 + x^2)) |
| 28 | +(x + 4atan((-1//4)*x), 0, 1.3318788420751984e-16) |
| 29 | + |
| 30 | +julia> integrate(x^2/sqrt(4 + x^2)) |
| 31 | +((1//2)*x*((4 + x^2)^0.5) - ((2//1)*log(x + sqrt(4 + x^2))), 0, 8.702422633074313e-17) |
| 32 | + |
| 33 | +julia> integrate(x^2*log(x)) |
| 34 | +((1//3)*log(x)*(x^3) - ((1//9)*(x^3)), 0, 0) |
| 35 | + |
| 36 | +julia> integrate(x^2*exp(x)) |
| 37 | +(2exp(x) + exp(x)*(x^2) - (2x*exp(x)), 0, 0) |
| 38 | + |
| 39 | +julia> integrate(tan(2x)) |
| 40 | +((-1//2)*log(cos(2x)), 0, 0) |
| 41 | + |
| 42 | +julia> integrate(sec(x)*tan(x)) |
| 43 | +(cos(x)^-1, 0, 0) |
| 44 | + |
| 45 | +julia> integrate(cosh(2x)*exp(x)) |
| 46 | +((2//3)*exp(x)*sinh(2x) - ((1//3)*exp(x)*cosh(2x)), 0, 7.073930088880992e-8) |
| 47 | + |
| 48 | +julia> integrate(cosh(x)*sin(x)) |
| 49 | +((1//2)*sin(x)*sinh(x) - ((1//2)*cos(x)*cosh(x)), 0, 4.8956233716268386e-17) |
| 50 | + |
| 51 | +julia> integrate(cosh(2x)*sin(3x)) |
| 52 | +(0.153845sinh(2x)*sin(3x) - (0.23077cosh(2x)*cos(3x)), 0, 4.9807620877373405e-6) |
| 53 | + |
| 54 | +julia> integrate(log(log(x))*(x^-1)) |
| 55 | +(log(x)*log(log(x)) - log(x), 0, 0) |
| 56 | + |
| 57 | +julia> integrate(exp(x^2)) |
| 58 | +(0, exp(x^2), Inf) # as expected! |
| 59 | +``` |
| 60 | + |
| 61 | +`integrate` has the form `integrate(y; kw...)` or `integrate(y, x; kw...)`, where `y` is the integrand and the optional `x` is the variable of integration. The keyword parameters are: |
| 62 | + |
| 63 | +* `abstol` (default `1e-6`): the error tolerance to accept a solution. |
| 64 | +* `symbolic` (default `true`): if true, pure symbolic integration is attempted first. |
| 65 | +* `bypass` (default `false`): if true, the whole expression is considered at once and not per term. |
| 66 | +* `num_steps` (default `2`): one plus the number of expanded basis to check (if `num_steps` is 1, only the main basis is checked). |
| 67 | +* `num_trials` (default `5`): the number of attempts to solve the integration numerically for each basis set. |
| 68 | +* `show_basis` (default `false`): print the basis set, useful for debugging. Only works if `verbose` is also set. |
| 69 | +* `homotopy` (default: `true` as of version 0.7.0): uses the continuous Homotopy operators to generate the integration candidates. |
| 70 | +* `verbose` (default `false`): if true, prints extra (and voluminous!) debugging information. |
| 71 | +* `radius` (default `1.0`): the starting radius to generate random test points. |
| 72 | +* `opt` (default `STLSQ(exp.(-10:1:0))`): the optimizer passed to `sparse_regression!`. |
| 73 | +* `max_basis` (default `110`): the maximum number of expression in the basis. |
| 74 | +* `complex_plane` (default `true`): random test points are generated on the complex plane (only over the real axis if `complex_plane` is `false`). |
| 75 | + |
| 76 | +## Testing |
| 77 | + |
| 78 | +`test/runtests.jl` contains a test suite of 160 easy to moderate test integrals (can be run by calling `test_integrals`). Currently, **SymbolicNumericIntegration.jl** solves more than 90% of its test suite. |
| 79 | + |
| 80 | +Additionally, 12 test suites from the *Rule-based Integrator* ([Rubi](https://rulebasedintegration.org/)) are included in the `/test` directory. For example, we can test the first one as below ([Axiom](http://www.axiom-developer.org/) refers to the format of the test files) |
| 81 | + |
| 82 | +```julia |
| 83 | + using SymbolicNumericIntegration |
| 84 | + include("test/axiom.jl") # note, you may need to use the correct path |
| 85 | + |
| 86 | + L = convert_axiom(:Apostle) # can also use L = convert_axiom(1) |
| 87 | + test_axiom(L, false; bypass=false, verbose=false, homotopy=true) |
| 88 | +``` |
| 89 | + |
| 90 | +The test suites description based on the header of the files in the Rubi directory are |
| 91 | + |
| 92 | +| name | id | comment | |
| 93 | +|-------------|----|------------------------------------------| |
| 94 | +|:Apostle | 1 | Tom M. Apostol - Calculus, Volume I, Second Edition (1967) | |
| 95 | +|:Bondarenko | 2 | Vladimir Bondarenko Integration Problems | |
| 96 | +|:Bronstein | 3 | Manuel Bronstein - Symbolic Integration Tutorial (1998) | |
| 97 | +|:Charlwood | 4 | Kevin Charlwood - Integration on Computer Algebra Systems (2008) | |
| 98 | +|:Hearn | 5 | Anthony Hearn - Reduce Integration Test Package | |
| 99 | +|:Hebisch | 6 | Waldek Hebisch - email May 2013 | |
| 100 | +|:Jeffrey | 7 | David Jeffrey - Rectifying Transformations for Trig Integration (1997) | |
| 101 | +|:Moses | 8 | Joel Moses - Symbolic Integration Ph.D. Thesis (1967) | |
| 102 | +|:Stewart | 9 | James Stewart - Calculus (1987) | |
| 103 | +|:Timofeev | 10 | A. F. Timofeev - Integration of Functions (1948) | |
| 104 | +|:Welz | 11 | Martin Welz - posts on Sci.Math.Symbolic | |
| 105 | +|:Webster | 12 | Michael Wester | |
| 106 | + |
| 107 | +## Citation |
| 108 | + |
| 109 | +If you use **SymbolicNumericIntegration.jl**, please cite [Symbolic-Numeric Integration of Univariate Expressions based on Sparse Regression](https://arxiv.org/abs/2201.12468): |
4 | 110 |
|
5 | | -```@autodocs |
6 | | -Modules = [SymbolicNumericIntegration] |
7 | 111 | ``` |
| 112 | +@article{Iravanian2022, |
| 113 | + author = {Shahriar Iravanian and Carl Julius Martensen and Alessandro Cheli and Shashi Gowda and Anand Jain and Julia Computing and Yingbo Ma and Chris Rackauckas}, |
| 114 | + doi = {10.48550/arxiv.2201.12468}, |
| 115 | + month = {1}, |
| 116 | + title = {Symbolic-Numeric Integration of Univariate Expressions based on Sparse Regression}, |
| 117 | + url = {https://arxiv.org/abs/2201.12468v2}, |
| 118 | + year = {2022}, |
| 119 | +} |
| 120 | +``` |
0 commit comments