Skip to content

Commit f6df29b

Browse files
committed
more updates on final report [skip ci]
1 parent e22266a commit f6df29b

File tree

1 file changed

+16
-15
lines changed

1 file changed

+16
-15
lines changed

GSoCfinalReport_MattiaMichelettaMerlin.md

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,20 @@ If you are in a hurry, read only the Project Overview section, and you should ha
1616
# Project Overview
1717

1818
- **GSoC Participant:** [Mattia Micheletta Merlin](https://mmm3.it/)
19-
- **Organization:** [NumFOCUS](https://numfocus.org/sponsored-projects) (under Julia [SciML](https://sciml.ai/) umbrella)
19+
- **Organization:** Julia [SciML](https://sciml.ai/) (under [NumFOCUS](https://numfocus.org/sponsored-projects) umbrella)
2020
- **Mentors:** Aayush Sabharwal, Chris Rackauckas
2121
- **Project in one sentence:** Rule-based symbolic integration in Julia
2222

23-
This project aimed to implement symbolic integration (i.e. finding primitives of functions, not numerical integration) in Symbolics.jl, the Julia package for symbolic manipulation. The chosen algorithm was rule-based integration, which uses a large number of integration rules that specify how to integrate various expressions. I chose this strategy thanks to the [Mathematica](https://www.wolfram.com/mathematica/) package [RUBI](https://rulebasedintegration.org/), which already contains more than 6000 integration rules and is open source.
23+
With this project I implemented symbolic integration (i.e. finding primitives of functions, not numerical integration) in [Symbolics.jl](https://docs.sciml.ai/Symbolics/stable/), the Julia package for symbolic manipulation. The chosen algorithm was rule-based integration, which uses a large number of integration rules that specify how to integrate various mathematical expressions. I chose this strategy thanks to the [Mathematica](https://www.wolfram.com/mathematica/) package [RUBI](https://rulebasedintegration.org/), which already contains more than 6000 integration rules and is open source.
2424

2525
The main challenges I encountered were:
26-
- **Rule translation:** The rules are written in Mathematica files with Mathematica syntax (very different from Julia syntax). I tackled this challenge by creating a translator script that automatically translates the rules into Julia syntax using regex and other string manipulation functions that I wrote. It's described in detail in the sections below
26+
- **Translation of integration rules:** The integration rules are written in Mathematica syntax (very different from Julia syntax). I tackled this challenge by creating a translator script that automatically translates them into Julia syntax using regexes and other fancy string manipulation functions that I wrote (it's described in detail in the sections below). Even with this script, I had to manually test the rules and this was time conusming.
2727

28-
- **Utility functions:** There are many rules in RUBI, but also many utility functions used in the rule conditions, including both base Mathematica functions and custom functions made for the RUBI package (the file where they are defined contains 7842 lines of code). The translation of these could not be automated, so I had to: 1) understand what each utility function did (not always easy) and 2) rewrite it in Julia.
28+
- **Utility functions:** There are many integration rules in RUBI, but also many utility functions used in the rule conditions, including both base Mathematica functions (usually not present in Symbolics.jl) and custom functions made for the RUBI package (the file where they are defined contains 7842 lines of code). The translation of these could not be automated and was a lot time consumning and error prone as I had to both understand what each utility function did (not always easy), rewrite it in Julia, and test its behaviour with lots of different rules.
2929

30-
- **Rule application:** Julia's Symbolics.jl already had a pattern matching functionality, with the `@rule` macro, but it was not sufficient for symbolic integration to work well, so I improved it. There was not one single big improvement but many small ones, described in detail in the sections below.
30+
- **Rule application:** Julia's Symbolics.jl already had a pattern matching functionality, with the `@rule` macro, but it was not sufficiently good for this package to work well, so I improved it. There was not one single big improvement but many small ones, described in detail in the sections below.
3131

32-
As of september 2025, end of GSoC, I translated 3000+ rules from 90+ files and the system can integrate a vast class of expressions, involving normal algebraic functions
32+
As of september 2025, end of GSoC, I translated more than 3400 rules and the system can integrate a vast class of expressions, involving normal algebraic functions:
3333
```julia
3434
julia> integrate(sqrt(4 - 12*x + 9*x^2)+sqrt(1+x),x)
3535
-------Applied rule 0_1_0 on (sqrt(1 + x) + sqrt(4 - 12x + 9(x^2)), x)
@@ -58,23 +58,23 @@ julia> integrate((2+2x+2x^2)/(1+x^3);verbose=false)
5858
julia> integrate((1 - x)^2*(1 + x)^(2.34);verbose=false)
5959
1.1976047904191618((1 + x)^3.34) - 0.9216589861751152((1 + x)^4.34) + 0.18726591760299627((1 + x)^5.34)
6060
```
61-
also symbolic ones
61+
also symbolic ones:
6262
```julia
6363
julia> integrate(1/(a+b*x^2),x;verbose=false)
6464
(atan(x / sqrt(a / b))*sqrt(a / b)) / a
6565

6666
julia> integrate(x^2/(1+a*x^3),x;verbose=false)
6767
log(1 + a*(x^3)) / (3a)
6868
```
69-
exponentials
69+
exponentials:
7070
```julia
7171
julia> integrate(exp(x)/(exp(2x)-1);verbose=false)
7272
-atanh(exp(x))
7373

7474
julia> integrate(sqrt(x)*exp(x);verbose=false)
7575
-0.8862269254527579SpecialFunctions.erfi(sqrt(x)) + sqrt(x)*exp(x)
7676
```
77-
logarithms
77+
logarithms:
7878
```julia
7979
julia> integrate(log(x)*x;verbose=false)
8080
-(1//4)*(x^2) + (1//2)*(x^2)*log(x)
@@ -85,7 +85,7 @@ julia> integrate(log(x)/sqrt(x);verbose=false)
8585
julia> integrate(log(log(x));verbose=false)
8686
-SpecialFunctions.expinti(log(x)) + x*log(log(x))
8787
```
88-
trigonometric functions
88+
trigonometric functions:
8989
```julia
9090
julia> integrate(sin(x)^3*cos(x)^2;verbose=false)
9191
-(1//3)*(cos(x)^3) + (1//5)*(cos(x)^5)
@@ -105,12 +105,12 @@ julia> integrate(sin(x^2)/x;verbose=false)
105105
julia> integrate(acosh(x+1);verbose=false)
106106
(1 + x)*acosh(1 + x) - sqrt(x)*sqrt(2 + x)
107107
```
108-
and much more. I also added 27585 tests (integrals with their correct solution) from the RUBI package that can be used to test the package.
108+
and much more. I also added 27585 tests (integrals with their correct solution) from the RUBI package and an automated testing procedure that can be used to test the package.
109109

110110
While this shows impressive integration capabilities, there is still work left to do, which I briefly list here and describe in detail below.
111-
- First, there are still some problems with the SymbolicUtils `@rule` macro that prevent some expressions from being integrated even though the rules are present.
112-
- There are still some rules not translated, mainly those involving trigonometric functions, hyperbolic functions, and special functions.
113-
- Finally, during the summer, a Julia package has been revived that performs symbolic integration using various algorithms, and we decided to create one unified package where the user can choose which integration strategy to use. I thus need to move all my code to that repository, the pr is underway: [pr](https://github.com/JuliaSymbolics/SymbolicIntegration.jl/pull/12).
111+
- Most importantly, there are still some problems with the SymbolicUtils `@rule` macro that prevent some expressions from being integrated even though the rules are present, and that slow down the package.
112+
- There are still some rules not translated, mainly those involving trigonometric functions, hyperbolic functions, and special functions.
113+
- Finally, during the summer, a Julia package has been revived that performs symbolic integration using various algorithms, and we decided to create one unified package where the user can choose which integration strategy to use. I thus need to move all my code to that repository, the [pull request](https://github.com/JuliaSymbolics/SymbolicIntegration.jl/pull/12) is underway.
114114

115115
# Detailed report of work done
116116
Here is a detailed report of the work done with links to code and pull requests (pr), if you really want to deep dive in the technical details. The code I have written is mainly in this repo, SymbolicIntegration.jl, and in the SymbolicUtils.jl repo where I improved the `@rule` macro.
@@ -123,6 +123,7 @@ added DefSlots | [pr](https://github.com/JuliaSymbolics/SymbolicUtils.jl/pull/74
123123
added commutative checks, <br> negative exponent matching, <br> `sqrt` and `exp` support <br> and new simplify behaviour (yes, all in one pr) | [pr](https://github.com/JuliaSymbolics/SymbolicUtils.jl/pull/752)
124124
return matches dictionary | [pr](https://github.com/JuliaSymbolics/SymbolicUtils.jl/pull/774)
125125
sped up rules | [pr](https://github.com/JuliaSymbolics/SymbolicUtils.jl/pull/779)
126+
documentation | [pr](https://github.com/JuliaSymbolics/SymbolicUtils.jl/pull/783)
126127

127128

128129
### Defslot
@@ -179,7 +180,7 @@ julia> arguments(sin(a)+cos(a))
179180
In the second case, it differs from the one defined in the rule (sin first, then cos). So I made the operations `+` and `*` commutative in rules.
180181

181182
### Negative Exponent Support
182-
Previously, a rule like `(~x)^(~m)` didn't match an expression like `1/x^3` with `~m=-3`, and this was crucial for the correct functioning of my package. So I changed this behavior, and now exponents can match divisions using a negative value as the exponent.
183+
Previously, a rule like `(~x)^(~m)` didn't match an expression like `1/x^3` with `~m=-3`, and this was crucial for the correct functioning of my package. So I changed this behavior, and now exponents can match divisions using a negative value as the exponent. This was trickier than it seems, because a division in SymbolicUtils can be represented in many ways: `(1/...)^(...))`, `1/(...)^(...)`, `1/(...)`, `(...)/(...)` and in fact in some rare cases this is still not working properly (read neim problem section below).
183184

184185
### Other Minor Enhancements
185186

0 commit comments

Comments
 (0)