Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/SymbolicIntegration.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ include("coupled_differential_systems.jl")
include("algebraic_functions.jl")
include("frontend.jl")

# Add method dispatch system
include("methods.jl")

# Export method interface
export AbstractIntegrationMethod, RischMethod

end # module
10 changes: 5 additions & 5 deletions src/frontend.jl
Original file line number Diff line number Diff line change
Expand Up @@ -766,27 +766,27 @@ integrate(exp(x), x) # exp(x)
integrate(log(x), x) # -x + x*log(x)
```
"""
function integrate(f::Symbolics.Num, x::Symbolics.Num; kwargs...)
function integrate_risch(f::Symbolics.Num, x::Symbolics.Num; kwargs...)
# Extract SymbolicUtils expressions from Symbolics.Num wrappers
result_symbolic = integrate(f.val, x.val; kwargs...)
result_symbolic = integrate_risch(f.val, x.val; kwargs...)
# Wrap result back in Symbolics.Num
return Symbolics.Num(result_symbolic)
end

struct AlgebraicNumbersInvolved <: Exception end

function integrate(f::SymbolicUtils.Add, x::SymbolicUtils.Symbolic; useQQBar::Bool=false,
function integrate_risch(f::SymbolicUtils.Add, x::SymbolicUtils.Symbolic; useQQBar::Bool=false,
catchNotImplementedError::Bool=true, catchAlgorithmFailedError::Bool=true)
# For efficiency compute integral of sum as sum of integrals
g = f.coeff*x
for (h, c) in f.dict
g += c*integrate(h, x, useQQBar=useQQBar, catchNotImplementedError=catchNotImplementedError,
g += c*integrate_risch(h, x, useQQBar=useQQBar, catchNotImplementedError=catchNotImplementedError,
catchAlgorithmFailedError=catchAlgorithmFailedError)
end
g
end

function integrate(f::SymbolicUtils.Symbolic, x::SymbolicUtils.Symbolic; useQQBar::Bool=false,
function integrate_risch(f::SymbolicUtils.Symbolic, x::SymbolicUtils.Symbolic; useQQBar::Bool=false,
catchNotImplementedError::Bool=true, catchAlgorithmFailedError::Bool=true)
try
p, funs, vars, args = analyze_expr(f, x)
Expand Down
89 changes: 89 additions & 0 deletions src/methods.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Method dispatch system for SymbolicIntegration.jl

"""
AbstractIntegrationMethod

Abstract supertype for all symbolic integration methods.
"""
abstract type AbstractIntegrationMethod end

"""
RischMethod <: AbstractIntegrationMethod

Risch algorithm for symbolic integration of elementary functions.

# Fields
- `use_algebraic_closure::Bool`: Whether to use algebraic closure for complex roots (default: true)
- `catch_errors::Bool`: Whether to catch and handle algorithm errors gracefully (default: true)
"""
struct RischMethod <: AbstractIntegrationMethod
use_algebraic_closure::Bool
catch_errors::Bool

function RischMethod(; use_algebraic_closure::Bool=true, catch_errors::Bool=true)
new(use_algebraic_closure, catch_errors)
end
end

"""
integrate(f, x, method::AbstractIntegrationMethod=RischMethod(); kwargs...)

Compute the symbolic integral of expression `f` with respect to variable `x`
using the specified integration method.

# Arguments
- `f`: Symbolic expression to integrate (Symbolics.Num)
- `x`: Integration variable (Symbolics.Num)
- `method`: Integration method to use (AbstractIntegrationMethod, default: RischMethod())

# Keyword Arguments
- Method-specific keyword arguments are passed to the method implementation

# Returns
- Symbolic expression representing the antiderivative (Symbolics.Num)

# Examples
```julia
using SymbolicIntegration, Symbolics
@variables x

# Using default Risch method
integrate(x^2, x) # (1//3)*(x^3)

# Explicit method with options
integrate(1/(x^2 + 1), x, RischMethod(use_algebraic_closure=true)) # atan(x)

# Method configuration
risch = RischMethod(use_algebraic_closure=false, catch_errors=true)
integrate(exp(x), x, risch) # exp(x)
```
"""
function integrate(f::Symbolics.Num, x::Symbolics.Num, method::RischMethod; kwargs...)
# Call renamed Risch function with method options
return integrate_risch(f, x;
useQQBar=method.use_algebraic_closure,
catchNotImplementedError=method.catch_errors,
catchAlgorithmFailedError=method.catch_errors,
kwargs...)
end

# Main integrate function - dispatches to RischMethod by default
function integrate(f::Symbolics.Num, x::Symbolics.Num; kwargs...)
return integrate_risch(f, x; kwargs...)
end

"""
method_supports_rational(method::RischMethod)

Check if the integration method supports rational function integration.
Returns `true` for RischMethod.
"""
method_supports_rational(method::RischMethod) = true

"""
method_supports_transcendental(method::RischMethod)

Check if the integration method supports transcendental function integration.
Returns `true` for RischMethod.
"""
method_supports_transcendental(method::RischMethod) = true
Loading