Skip to content
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

Add dep on SymbolicLimits.jl and export limit #1096

Merged
merged 5 commits into from
Mar 21, 2024
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
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
Loading