Skip to content

Commit

Permalink
Merge pull request #1096 from LilithHafner/lh/limits
Browse files Browse the repository at this point in the history
Add dep on SymbolicLimits.jl and export `limit`
  • Loading branch information
ChrisRackauckas authored Mar 21, 2024
2 parents 1c42985 + dec5bd3 commit fc2c87e
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5"
SymbolicLimits = "19f23fe9-fdab-4a78-91af-e7b7767979c3"
SymbolicUtils = "d1185830-fcd6-423d-90d6-eec64667417b"

[weakdeps]
Expand Down Expand Up @@ -81,6 +82,7 @@ Setfield = "1"
SpecialFunctions = "2"
StaticArrays = "1.1"
SymbolicIndexingInterface = "0.3"
SymbolicLimits = "0.2.0"
SymbolicUtils = "1.4"
julia = "1.10"

Expand Down
3 changes: 2 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ makedocs(
"manual/io.md",
"manual/sparsity_detection.md",
"manual/types.md",
"manual/faq.md"
"manual/faq.md",
"manual/limits.md",
],
"Comparison Against SymPy" => "comparison.md",
]
Expand Down
9 changes: 9 additions & 0 deletions docs/src/manual/limits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Symbolic Limits

Experimental symbolic limit support is provided by the [`limit`](@ref) function, documented
below. See [SymbolicLimits.jl](https://github.com/SciML/SymbolicLimits.jl) for more
information and implementation details.

```@docs
limit
```
5 changes: 5 additions & 0 deletions src/Symbolics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ using PrecompileTools
using MacroTools

using SymbolicIndexingInterface

import SymbolicLimits
end
@reexport using SymbolicUtils
RuntimeGeneratedFunctions.init(@__MODULE__)
Expand Down Expand Up @@ -149,6 +151,9 @@ include("error_hints.jl")
include("struct.jl")
include("operators.jl")

include("limits.jl")
export limit

# Hacks to make wrappers "nicer"
const NumberTypes = Union{AbstractFloat,Integer,Complex{<:AbstractFloat},Complex{<:Integer}}
(::Type{T})(x::SymbolicUtils.Symbolic) where {T<:NumberTypes} = throw(ArgumentError("Cannot convert Sym to $T since Sym is symbolic and $T is concrete. Use `substitute` to replace the symbolic unwraps."))
Expand Down
20 changes: 20 additions & 0 deletions src/limits.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""
limit(expr, var, h[, side::Symbol])
Compute the limit of `expr` as `var` approaches `h`.
`side` indicates the direction from which `var` approaches `h`. It may be one of `:left`,
`:right`, or `:both`. If `side` is `:both` and the two sides do not align, an error is
thrown. Side defaults to `:both` for finite `h`, `:left` for `h = Inf`, and `:right` for
`h = -Inf`.
`expr` must be compoesed of `log`, `exp`, constants, and the rational opperators `+`, `-`,
`*`, and `/`. This limitation may eventually be relaxed.
!!! warning
Because symbolic limit computation is undecidable, this function necessarily employs
heuristics and may occasionally return wrong answers. Nevertheless, please report wrong
answers as issues as we aim to have heuristics that produce correct answers in all
practical cases.
"""
limit(expr, var, h, side...) = SymbolicLimits.limit(expr, var, h, side...)[1]
13 changes: 13 additions & 0 deletions test/limits.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Symbolics, Test

@testset "limits" begin
@syms x
@test limit(exp(x+exp(-x))-exp(x), x, Inf) == 1
@test limit(x^7/exp(x), x, Inf) == 0
@test limit(log(log(x*exp(x*exp(x))+1))-exp(exp(log(log(x))+1/x)), x, Inf) == 0
@test limit(2exp(-x)/exp(-x), x, 0) == 2

@test_throws ArgumentError limit(1/x, x, 0)
@test limit(1/x, x, 0, :left)[1] == -Inf
@test limit(1/x, x, 0, :right)[1] == Inf
end

0 comments on commit fc2c87e

Please sign in to comment.