Skip to content

Commit 6a5f3b5

Browse files
Merge pull request #5 from ChrisRackauckas-Claude/refactor-risch-method
Refactor to SciML-style method dispatch system
2 parents aa49525 + 4be92e1 commit 6a5f3b5

File tree

3 files changed

+100
-5
lines changed

3 files changed

+100
-5
lines changed

src/SymbolicIntegration.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,10 @@ include("coupled_differential_systems.jl")
1313
include("algebraic_functions.jl")
1414
include("frontend.jl")
1515

16+
# Add method dispatch system
17+
include("methods.jl")
18+
19+
# Export method interface
20+
export AbstractIntegrationMethod, RischMethod
21+
1622
end # module

src/frontend.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -766,27 +766,27 @@ integrate(exp(x), x) # exp(x)
766766
integrate(log(x), x) # -x + x*log(x)
767767
```
768768
"""
769-
function integrate(f::Symbolics.Num, x::Symbolics.Num; kwargs...)
769+
function integrate_risch(f::Symbolics.Num, x::Symbolics.Num; kwargs...)
770770
# Extract SymbolicUtils expressions from Symbolics.Num wrappers
771-
result_symbolic = integrate(f.val, x.val; kwargs...)
771+
result_symbolic = integrate_risch(f.val, x.val; kwargs...)
772772
# Wrap result back in Symbolics.Num
773773
return Symbolics.Num(result_symbolic)
774774
end
775775

776776
struct AlgebraicNumbersInvolved <: Exception end
777777

778-
function integrate(f::SymbolicUtils.Add, x::SymbolicUtils.Symbolic; useQQBar::Bool=false,
778+
function integrate_risch(f::SymbolicUtils.Add, x::SymbolicUtils.Symbolic; useQQBar::Bool=false,
779779
catchNotImplementedError::Bool=true, catchAlgorithmFailedError::Bool=true)
780780
# For efficiency compute integral of sum as sum of integrals
781781
g = f.coeff*x
782782
for (h, c) in f.dict
783-
g += c*integrate(h, x, useQQBar=useQQBar, catchNotImplementedError=catchNotImplementedError,
783+
g += c*integrate_risch(h, x, useQQBar=useQQBar, catchNotImplementedError=catchNotImplementedError,
784784
catchAlgorithmFailedError=catchAlgorithmFailedError)
785785
end
786786
g
787787
end
788788

789-
function integrate(f::SymbolicUtils.Symbolic, x::SymbolicUtils.Symbolic; useQQBar::Bool=false,
789+
function integrate_risch(f::SymbolicUtils.Symbolic, x::SymbolicUtils.Symbolic; useQQBar::Bool=false,
790790
catchNotImplementedError::Bool=true, catchAlgorithmFailedError::Bool=true)
791791
try
792792
p, funs, vars, args = analyze_expr(f, x)

src/methods.jl

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Method dispatch system for SymbolicIntegration.jl
2+
3+
"""
4+
AbstractIntegrationMethod
5+
6+
Abstract supertype for all symbolic integration methods.
7+
"""
8+
abstract type AbstractIntegrationMethod end
9+
10+
"""
11+
RischMethod <: AbstractIntegrationMethod
12+
13+
Risch algorithm for symbolic integration of elementary functions.
14+
15+
# Fields
16+
- `use_algebraic_closure::Bool`: Whether to use algebraic closure for complex roots (default: true)
17+
- `catch_errors::Bool`: Whether to catch and handle algorithm errors gracefully (default: true)
18+
"""
19+
struct RischMethod <: AbstractIntegrationMethod
20+
use_algebraic_closure::Bool
21+
catch_errors::Bool
22+
23+
function RischMethod(; use_algebraic_closure::Bool=true, catch_errors::Bool=true)
24+
new(use_algebraic_closure, catch_errors)
25+
end
26+
end
27+
28+
"""
29+
integrate(f, x, method::AbstractIntegrationMethod=RischMethod(); kwargs...)
30+
31+
Compute the symbolic integral of expression `f` with respect to variable `x`
32+
using the specified integration method.
33+
34+
# Arguments
35+
- `f`: Symbolic expression to integrate (Symbolics.Num)
36+
- `x`: Integration variable (Symbolics.Num)
37+
- `method`: Integration method to use (AbstractIntegrationMethod, default: RischMethod())
38+
39+
# Keyword Arguments
40+
- Method-specific keyword arguments are passed to the method implementation
41+
42+
# Returns
43+
- Symbolic expression representing the antiderivative (Symbolics.Num)
44+
45+
# Examples
46+
```julia
47+
using SymbolicIntegration, Symbolics
48+
@variables x
49+
50+
# Using default Risch method
51+
integrate(x^2, x) # (1//3)*(x^3)
52+
53+
# Explicit method with options
54+
integrate(1/(x^2 + 1), x, RischMethod(use_algebraic_closure=true)) # atan(x)
55+
56+
# Method configuration
57+
risch = RischMethod(use_algebraic_closure=false, catch_errors=true)
58+
integrate(exp(x), x, risch) # exp(x)
59+
```
60+
"""
61+
function integrate(f::Symbolics.Num, x::Symbolics.Num, method::RischMethod; kwargs...)
62+
# Call renamed Risch function with method options
63+
return integrate_risch(f, x;
64+
useQQBar=method.use_algebraic_closure,
65+
catchNotImplementedError=method.catch_errors,
66+
catchAlgorithmFailedError=method.catch_errors,
67+
kwargs...)
68+
end
69+
70+
# Main integrate function - dispatches to RischMethod by default
71+
function integrate(f::Symbolics.Num, x::Symbolics.Num; kwargs...)
72+
return integrate_risch(f, x; kwargs...)
73+
end
74+
75+
"""
76+
method_supports_rational(method::RischMethod)
77+
78+
Check if the integration method supports rational function integration.
79+
Returns `true` for RischMethod.
80+
"""
81+
method_supports_rational(method::RischMethod) = true
82+
83+
"""
84+
method_supports_transcendental(method::RischMethod)
85+
86+
Check if the integration method supports transcendental function integration.
87+
Returns `true` for RischMethod.
88+
"""
89+
method_supports_transcendental(method::RischMethod) = true

0 commit comments

Comments
 (0)