-
Notifications
You must be signed in to change notification settings - Fork 7
Add rule based integration method #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9999351
aebf2e6
d82394e
4faa2f8
cd43c01
6cc141f
d66c3be
aa55dca
20279a8
cfd4282
6e027a6
4b1496a
df175a7
914835c
2d8b6e8
34660b8
590f735
7305d97
4e76fe9
42b9d0d
9b97403
17810ee
f556f92
c3344a9
37f4cd0
298a290
dec854d
5bc1e6f
9a81502
98ec6c8
904992c
c46e9b9
2a50f77
37da574
1b9b521
81ced17
3ab5525
0e6cd33
be9de1c
46782c1
4361cb6
fc7095d
bcf2741
efd5847
6f7c299
5d3225f
b106843
06c2530
be2a813
150b5d4
be011b7
1f774ae
6f510b0
7cf5fcc
388df4e
0909714
1eaf984
6209137
f0d1f4c
46b261d
11812fb
03aafdd
17bc246
238f20f
3ae0394
1ae7eb3
e2c51d3
5857c27
99c414b
f8693fa
68f79e4
4b40e2e
352530a
174f2d5
10c636d
f9e68a1
35b4c58
6ded12e
fe0fb6d
63cb323
ccdb5c4
57d689c
844eff5
eda068c
e615d69
2ed2323
9e6b036
3f67972
3d5e11a
b807d8e
8b2eba5
90ebac9
c4d00ab
b991729
fa608a1
98393b1
b25f595
5574603
a949c97
011e1f0
0e77376
097f520
efbb38a
6a4f088
838b710
9f380c7
bda33a3
3578e70
9e64ccd
39f9af4
088f64e
c7f83d6
d327f6e
e7981ac
80cf26b
9288d1a
bff7fe4
b310876
84fd1d6
4d11b6a
b3a6fc6
00d4c90
6f7089e
84808c5
e61f4cd
bc74bfe
836c9b1
1bb5ac5
70d3769
331a8af
d69247a
ad54f28
0123d49
2128b69
874db16
00b3868
ca57399
0dc116d
9c7a44b
9335822
cb44d34
a0b48a4
b488729
c587583
b04db62
4044f0b
8578f67
178613c
7816085
b5c6d36
71384f2
840ba36
a786852
8f42af2
431a2e7
9f01570
3b21d1c
1b2e89a
3b88436
31b3425
93fb035
a489909
d9c9519
e8f7875
1f59729
ffd44d7
7a885b1
eaf880f
19cc97f
88fa6fc
c4c8754
eab91a3
a44758e
ace1c7d
6451d44
8cfa888
b27401a
b9e68b0
5c84a1a
3144438
66d126b
298c1ba
46a1b03
a622acb
dbba3ed
88641ae
d97c609
6e37653
f69b12a
0aa8f93
84c8140
d520878
a53ffc2
4841e13
dd79968
1fc3fe7
c537029
ab54a3f
329b30e
8e36783
0fde30a
ccbec4c
20a543e
2b3a361
aee2e38
01bf063
4b3d573
2d5ce82
9ff7048
469dc5a
f28b728
a5c9488
99811ff
4d14177
afb0336
5e64be5
0fd109d
033d521
3fd5351
afbfe7d
e62d94a
049c278
43e380c
339b361
5a01930
c1baf63
a71a734
e0f405f
54cf820
57a9f3d
85dda75
752a2cb
c168049
1823504
a6f9c85
eaa136a
cf90227
81a6b74
7db7cff
809b007
6ac197e
5a5aa7e
3b9355f
35ce25f
81826c2
f7ab23d
274e0aa
a5419e9
2c0c425
8344d68
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "schemaVersion": 1, | ||
| "label": "Total rules", | ||
| "message": "3399", | ||
| "color": "blue" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates | ||
| version: 2 | ||
| updates: | ||
| - package-ecosystem: "github-actions" | ||
| directory: "/" # Location of package manifests | ||
| schedule: | ||
| interval: "weekly" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| name: Spell Check | ||
|
|
||
| on: [push, pull_request] | ||
|
|
||
| jobs: | ||
| typos-check: | ||
| name: Spell Check with Typos | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout Actions Repository | ||
| uses: actions/checkout@v4 | ||
| - name: Check spelling | ||
| uses: crate-ci/typos@v1.16.23 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,28 +1,40 @@ | ||
| name = "SymbolicIntegration" | ||
| uuid = "315ce56f-eed0-411d-ab8a-2fbdf9327b51" | ||
| authors = ["HaraldHofstaetter <hofi@harald-hofstaetter.at>", "Chris Rackauckas <accounts@chrisrackauckas.com>", "JuliaSymbolics contributors"] | ||
| version = "2.0.0" | ||
| keywords = ["symbolic", "integration", "mathematics", "computer-algebra"] | ||
| license = "MIT" | ||
| authors = ["HaraldHofstaetter <hofi@harald-hofstaetter.at>", "Mattia Micheletta Merlin <micheletta.mattia@gmail.com>", "Chris Rackauckas <accounts@chrisrackauckas.com>", "JuliaSymbolics contributors"] | ||
| description = "Symbolic integration algorithms for Julia" | ||
| repository = "https://github.com/JuliaSymbolics/SymbolicIntegration.jl" | ||
| license = "MIT" | ||
| keywords = ["symbolic", "integration", "mathematics", "computer-algebra"] | ||
| version = "2.0.0" | ||
|
|
||
| [deps] | ||
| AbstractAlgebra = "c3fe647b-3220-5bb0-a1ea-a7954cac585d" | ||
| Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" | ||
| Elliptic = "b305315f-e792-5b7a-8f41-49f472929428" | ||
| FresnelIntegrals = "88497964-e39a-11e9-0fb5-b1bf0ffe80fe" | ||
| HypergeometricFunctions = "34004b35-14d8-5ef3-9330-4cdb6864b03a" | ||
| Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" | ||
| Nemo = "2edaba10-b0f1-5616-af89-8c11ac63239a" | ||
| PolyLog = "85e3b03c-9856-11eb-0374-4dc1f8670e7f" | ||
| SymbolicUtils = "d1185830-fcd6-423d-90d6-eec64667417b" | ||
| Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" | ||
|
|
||
| [compat] | ||
| AbstractAlgebra = "0.46" | ||
| Combinatorics = "1.0.2" | ||
| Elliptic = "1.0.1" | ||
| FresnelIntegrals = "0.2.0" | ||
| HypergeometricFunctions = "0.3.28" | ||
| Nemo = "0.51" | ||
| PolyLog = "2.6.0" | ||
| SymbolicUtils = "3" | ||
| Symbolics = "6" | ||
| julia = "1.10" | ||
|
|
||
| [extras] | ||
| Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" | ||
| Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" | ||
| Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" | ||
|
|
||
| [targets] | ||
| test = ["Test"] | ||
| test = ["Test", "Pkg", "Dates"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,119 +1,105 @@ | ||
| # SymbolicIntegration.jl | ||
|
|
||
| *A unified interface for symbolic integration methods in Julia* | ||
| [](https://github.com/JuliaSymbolics/SymbolicIntegration.jl/actions/workflows/CI.yml?query=branch%3Amain) | ||
| [](https://github.com/JuliaSymbolics/SymbolicIntegration.jl/actions/workflows/spellcheck.yml) | ||
| [](https://github.com/JuliaSymbolics/SymbolicIntegration.jl) | ||
|
|
||
| SymbolicIntegration.jl provides a flexible, extensible framework for symbolic integration with multiple algorithm choices. The package uses method dispatch to allow users to select the most appropriate integration algorithm for their specific needs. | ||
|
|
||
| ## Key Features | ||
| SymbolicIntegration.jl solves indefinite integrals using one of the implemented algorithms: Risch method and Rule based method | ||
|
|
||
| - 🎯 **Multiple Integration Methods**: Extensible method dispatch system | ||
| - ⚡ **Exact Symbolic Results**: Guaranteed correct symbolic integration | ||
| - 🔢 **Complex Root Handling**: Produces exact arctangent terms | ||
| - ⚙️ **Configurable Algorithms**: Method-specific options and behavior | ||
| - 🏗️ **Professional Interface**: SciML-style method selection | ||
|
|
||
| ## Integration Methods | ||
|
|
||
| ### RischMethod (Default) | ||
| Complete symbolic integration using the Risch algorithm from Manuel Bronstein's "Symbolic Integration I: Transcendental Functions". | ||
|
|
||
| **Capabilities:** | ||
| - ✅ **Rational functions**: Complete integration with Rothstein-Trager method | ||
| - ✅ **Transcendental functions**: Exponential, logarithmic using differential field towers | ||
| - ✅ **Complex roots**: Exact arctangent terms for complex polynomial roots | ||
| - ✅ **Integration by parts**: Logarithmic function integration | ||
| - ✅ **Trigonometric functions**: Via transformation to exponential form | ||
|
|
||
| **Function Classes:** | ||
| - Polynomial functions: `∫x^n dx`, `∫(ax^2 + bx + c) dx` | ||
| - Rational functions: `∫P(x)/Q(x) dx` → logarithmic and arctangent terms | ||
| - Exponential functions: `∫exp(f(x)) dx`, `∫x*exp(x) dx` | ||
| - Logarithmic functions: `∫log(x) dx`, `∫1/(x*log(x)) dx` | ||
| - Trigonometric functions: `∫sin(x) dx`, `∫cos(x) dx`, `∫tan(x) dx` | ||
|
|
||
| The framework is designed to support additional integration methods as they are developed. | ||
|
|
||
|
|
||
|
|
||
| ## Installation | ||
| # Usage | ||
| ```julia | ||
| julia> using Pkg; Pkg.add("SymbolicIntegration") | ||
| ``` | ||
| julia> using Pkg; Pkg.add("SymbolicIntegration") # installation | ||
|
|
||
| ## Usage | ||
| julia> using SymbolicIntegration, Symbolics | ||
|
|
||
| ### Basic Integration | ||
| julia> @variables x | ||
| 1-element Vector{Num}: | ||
| x | ||
|
|
||
| ```julia | ||
| using SymbolicIntegration, Symbolics | ||
| @variables x | ||
|
|
||
| # Default method (RischMethod) - most cases | ||
| integrate(x^2, x) # (1//3)*(x^3) | ||
| integrate(1/x, x) # log(x) | ||
| integrate(exp(x), x) # exp(x) | ||
| integrate(1/(x^2 + 1), x) # atan(x) | ||
| julia> integrate(exp(2x) + 2x^2 + sin(x)) | ||
| (1//2)*exp(2x) + (2//3)*(x^3) - cos(x) | ||
| ``` | ||
| The first argument is the expression to integrate, second argument is the variable of integration. If the variable is not specified, it will be guessed from the expression. The +c is omitted :) | ||
|
|
||
| ### Method Selection | ||
|
|
||
| You can explicitly choose a integration method like this: | ||
| ```julia | ||
| # Explicit method choice | ||
| integrate(f, x, RischMethod()) | ||
|
|
||
| # Method with configuration | ||
| risch = RischMethod(use_algebraic_closure=true, catch_errors=false) | ||
| integrate(f, x, risch) | ||
| ``` | ||
| or like this: | ||
| ```julia | ||
| rbm = RuleBasedMethod(verbose=true, use_gamma=false) | ||
| integrate(f, x, rbm) | ||
| ``` | ||
|
|
||
| If no method is specified, first RischMethod will be tried, then RuleBasedMethod: | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should probably be flipped? Rule based should usually be much quicker to converge?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rule based is fast, but the first times you call it it's quite slow because of compliation time of all the rules callable objects. Aayush suggested to use PrecompileTools.jl to precompile a integrate call on a expression that uses a rule at the end of the list, to precompile them all. But I didn't yet do it. Anyway yes we could flip them
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Risch methods are super slow though. They can take a way long time to compute, and actually can have unbounded runtime.
Yeah I can handle that. Let's first just get something correct and good enough to merge, then follow up with some improvements.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes |
||
| ```julia | ||
| julia> integrate(sqrt(x)) | ||
| ┌ Warning: NotImplementedError: integrand contains unsupported expression sqrt(x) | ||
| └ @ SymbolicIntegration ~/.julia/dev/SymbolicIntegration.jl_official/src/methods/risch/frontend.jl:826 | ||
|
|
||
| ### Complex Examples | ||
| > RischMethod failed returning ∫(sqrt(x), x) | ||
| > Trying with RuleBasedMethod... | ||
|
|
||
| (2//3)*(x^(3//2)) | ||
| ``` | ||
| ```julia | ||
| # Rational function with complex roots | ||
| f = (x^3 + x^2 + x + 2)/(x^4 + 3*x^2 + 2) | ||
| integrate(f, x) # (1//2)*log(2 + x^2) + atan(x) | ||
| julia> integrate(abs(x)) | ||
| ┌ Warning: NotImplementedError: integrand contains unsupported expression abs(x) | ||
| └ @ SymbolicIntegration ~/.julia/dev/SymbolicIntegration.jl_official/src/methods/risch/frontend.jl:826 | ||
|
|
||
| > RischMethod failed returning ∫(abs(x), x) | ||
| > Trying with RuleBasedMethod... | ||
|
|
||
| # Integration by parts | ||
| integrate(log(x), x) # -x + x*log(x) | ||
| No rule found for ∫(abs(x), x) | ||
|
|
||
| > RuleBasedMethod failed returning ∫(abs(x), x) | ||
| > Sorry we cannot integrate this expression :( | ||
|
|
||
| # Nested transcendental functions | ||
| integrate(1/(x*log(x)), x) # log(log(x)) | ||
| ``` | ||
|
|
||
| ## Method Framework | ||
|
|
||
| SymbolicIntegration.jl uses a modern method dispatch system similar to other SciML packages: | ||
| # Integration Methods | ||
| Currently two algorithms are implemented: **Risch algorithm** and **Rule based integration**. | ||
|
|
||
| ### Current Methods | ||
| - **RischMethod**: Complete symbolic integration (default) | ||
| feature | Risch | Rule based | ||
| --------|-------|----------- | ||
| rational functions | ✅ | ✅ | ||
| non integers powers | ❌ | ✅ | ||
| exponential functions | ✅ | ✅ | ||
| logarithms | ✅ | ✅ | ||
| trigonometric functions | ? | sometimes | ||
| hyperbolic functions | ✅ | sometimes | ||
| Nonelementary integrals | ❌ | most of them | ||
| Special functions | ❌ | ❌ | ||
| more than one symbolic<br> variable in the expression | ❌ | ✅ | ||
|
|
||
| ### Method Configuration | ||
| ```julia | ||
| # Research configuration (strict, complete) | ||
| RischMethod(use_algebraic_closure=true, catch_errors=false) | ||
| More info about them in the [methods documentation](methods/overview.md) | ||
|
|
||
| # Production configuration (robust, graceful) | ||
| RischMethod(use_algebraic_closure=true, catch_errors=true) | ||
| ### Risch Method | ||
| Complete symbolic integration using the Risch algorithm from Manuel Bronstein's "Symbolic Integration I: Transcendental Functions". | ||
|
|
||
| # Performance configuration (faster, simpler) | ||
| RischMethod(use_algebraic_closure=false, catch_errors=true) | ||
| ``` | ||
| ### RuleBasedMethod | ||
|
|
||
| ### Extensibility | ||
| The framework is designed for easy extension with additional integration methods. The abstract type `AbstractIntegrationMethod` provides the foundation for implementing new algorithms. | ||
| This method uses a large number of integration rules that specify how to integrate various mathematical expressions. There are now more than 3400 rules impelmented. | ||
|
|
||
| ## Documentation | ||
| # Documentation | ||
|
|
||
| Complete documentation with method selection guidance, algorithm details, and examples is available at: | ||
| **[https://symbolicintegration.juliasymbolics.org](https://symbolicintegration.juliasymbolics.org)** | ||
|
|
||
| ## Citation | ||
|
|
||
| # Citation | ||
|
|
||
| If you use SymbolicIntegration.jl in your research, please cite: | ||
|
|
||
| ```bibtex | ||
| @software{SymbolicIntegration.jl, | ||
| author = {Harald Hofstätter and contributors}, | ||
| author = {Harald Hofstätter and Mattia Micheletta Merlin and Chris Rackauckas}, | ||
| title = {SymbolicIntegration.jl: Symbolic Integration for Julia}, | ||
| url = {https://github.com/JuliaSymbolics/SymbolicIntegration.jl}, | ||
| year = {2023-2025} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the changes to the README should be reverted. It's just an advertisement. Show people what's in the package to get them to open the docs. But it shouldn't go into detail about contributing etc. etc. that's all for deeper docs pages. Very quick overview, highlight how to use the package, and get someone to click the docs link.