Rule-based symbolic integration for Symbolica, based on the 7000+ Rubi integration rules.
use symbolica_integrate::Integrate;
use symbolica::prelude::*;
let x = symbol!("x");
let integrand = parse!("cos(a*x)*sin(b*x)");
let primitive = integrand
.integrate(x)
.unwrap();
println!("{primitive}");1/2*cos(x*(-a+b))/(a-b)-1/2*cos(x*(a+b))/(a+b)
Enable the steps feature to retain Rubi's rule sources and short
transformation descriptions, and use integrate_with_steps to obtain an
outer-to-inner derivation:
use symbolica::prelude::*;
use symbolica_integrate::Integrate;
let steps = parse!("x/(x+1)").integrate_with_steps(symbol!("x"));
println!("{explanation}");∫ x/(1+x) dx = ∫ 1-1/(1+x) dx
∫ 1-1/(1+x) dx = ∫ 1 dx+∫ 1/(-1-x) dx
∫ 1 dx = x
∫ -1/(1+x) dx = -log(1+x)
= x-log(1+x)
symbolica-integrate passes the complete 72,944-problem corpus. It takes 18 minutes of wall time, on a Ryzen 9 5900X with 8 cores. The measured time per problem had
a 57 ms median, 118 ms average, and 10.8 s maximum.
These timings are competitive, as an integration run on the independent test suite consisting of 1,892 problems shows:
| Integrator | Time |
|---|---|
symbolica-integrate |
111.24 s |
| Rubi 4.17.3.0 in Mathematica 13.2 | 155.78 s |
Symja Integrate 3.3.0 1 |
≥ 1,316.02 s |
In these runs, symbolica-integrate was 1.40× faster than Rubi in
Mathematica and at least 11.83× faster than Symja.
Rubi was created by Albert D. Rich and is currently maintained by Patrick Scheibe and others. See the Rubi website for more information.
This port aims to preserve Rubi's 7000+ rule ordering and integration routes while using Symbolica's native expression and pattern-matching infrastructure.
symbolica-integrate is released under the MIT License. It depends
on Symbolica, which is distributed under separate licensing
terms.
Footnotes
-
Symja timed out on 18 problems. ↩