Skip to content

first draft of precompute API #112

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

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
name = "LogDensityProblems"
uuid = "6fdf6af0-433a-55f7-b3ed-c6c6e0b8df7c"
authors = ["Tamas K. Papp <[email protected]>"]
version = "2.1.2"
authors = ["Tamas K. Papp <[email protected]>"]

[deps]
ArgCheck = "dce04be8-c92d-5529-be00-80e4d2c0e197"
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[compat]
ArgCheck = "1, 2"
Compat = "4.16.0"
DocStringExtensions = "0.8, 0.9"
julia = "1.10"

Expand Down
16 changes: 15 additions & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ end
If the gradient is a mutable vector (eg `Vector`), it should not be reused for another purpose. Practically, each call to [`LogDensityProblems.logdensity_and_gradient`](@ref) should allocate a new one, or use immutables like
`StaticArrays.SVector` for small dimensions.

# Precomputation API

FIXME

# Various utilities

You may find these utilities useful for debugging and optimization.
Expand All @@ -180,7 +184,7 @@ LogDensityProblems.stresstest

# [Log densities API](@id log-density-api)

Use the functions below for evaluating gradients and querying their dimension and other information. These symbols are not exported, as they are mostly used by package developers and in any case would need to be `import`ed or qualified to add methods to.
Use the functions below for evaluating gradients and querying their dimension and other information. These symbols are `public`, but not exported, as they are mostly used by package developers and in any case would need to be `import`ed or qualified to add methods to.

```@docs
LogDensityProblems.capabilities
Expand All @@ -190,3 +194,13 @@ LogDensityProblems.logdensity
LogDensityProblems.logdensity_and_gradient
LogDensityProblems.logdensity_gradient_and_hessian
```

The methods below only need to be implemented for storing precomputed information with coordinates, otherwise the defaults just work.

```@docs
LogDensityProblems.precompute
LogDensityProblems.move
LogDensityProblems.move!
```


82 changes: 80 additions & 2 deletions src/LogDensityProblems.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
using ArgCheck: @argcheck
using DocStringExtensions: SIGNATURES, TYPEDEF
using Random: AbstractRNG, default_rng
using Compat: @compat

@compat public LogDensityOrder, capabilities, dimension, logdensity, logdensity_and_gradient,
logdensity_gradient_and_hessian, precompute, move, move!

####
#### interface for problems
Expand Down Expand Up @@ -51,7 +55,7 @@

# Interface description

The following methods need to be implemented for the interface:
The following methods **need to be implemented** for the interface:

1. [`dimension`](@ref) returns the *dimension* of the domain,

Expand All @@ -61,7 +65,34 @@

4. [`logdensity_gradient_and_hessian`](@ref) when `K ≥ 2`.

See also [`LogDensityProblems.stresstest`](@ref) for stress testing.
The precomputation API (see below) has sensible fallbacks and should only be implemented
as needed.

# Coordinate points with precomputed information

The interface also allows for encapsulating extra information associated with
coordinates. The idea is that a coordinate ``x ∈ ℝⁿ`` may be associated with quantities
precomputed from `x` (such as solutions to implicit equations), which can be updated at
a lower computational cost when the position is changed instead of recomputed from
scratch.

The following methods **may be implemented**; but if they are not needed for your
application this package provides sensible defaults.

1. A type that encapsulates the precomputed information. It should be
`<:AbstractVector{T}` for some `T` and support the read-only interface for vectors,
ie `Base.size` and `Base.getindex`. When used as a vector, it should just correspond
to the position in ``ℝⁿ``.

2. [`precompute`](@ref), which precomputes the relevant information and returns objects of the
type above.

3. [`move`](@ref) and [`move!`](@ref) to change the coordinates and recompute the
associated information.

# See also

[`LogDensityProblems.stresstest`](@ref) for stress testing.
"""
capabilities(T::Type) = nothing

Expand Down Expand Up @@ -151,6 +182,53 @@
"""
function logdensity_gradient_and_hessian end

"""
$(SIGNATURES)

Precompute information associated with the coordinates `x` and return it as a
user-defined type.

Cf [`move`](@ref).
"""
function precompute(ℓ, x::AbstractVector{T}) where T
if T <: AbstractFloat
x

Check warning on line 195 in src/LogDensityProblems.jl

View check run for this annotation

Codecov / codecov/patch

src/LogDensityProblems.jl#L193-L195

Added lines #L193 - L195 were not covered by tests
else
float.(x)

Check warning on line 197 in src/LogDensityProblems.jl

View check run for this annotation

Codecov / codecov/patch

src/LogDensityProblems.jl#L197

Added line #L197 was not covered by tests
end
end

"""
$(SIGNATURES)

Change the coordinates by `Δ`. Conceptually equivalent to `x .+ Δ`, which is the
fallback implementation, but user-defined types for the second argument can take
advantage of the information there to compute the new associated information for small
changes.

The result should be **the same type** as `x` if `eltype(x) ≡ eltype(Δ)`.

Caller ensures that `x` is the result of [`precompute`](@ref). It is valid for an
implementation to error in all other cases.
"""
move(ℓ, x::AbstractVector, Δ) = x .+ Δ

Check warning on line 214 in src/LogDensityProblems.jl

View check run for this annotation

Codecov / codecov/patch

src/LogDensityProblems.jl#L214

Added line #L214 was not covered by tests

"""
$(SIGNATURES)

Equivalent to [`move`](@ref), but *may* modify `x`, which is returned, or choose to
return a new value.

If a new value is returned, it should be the same type as `x` if `eltype(x) ≡ eltype(Δ)`.

Caller ensures that `x` is the result of [`precompute`](@ref). It is valid for an
implementation to error in all other cases.
"""
function move!(ℓ, x::AbstractVector, Δ)
x .+= Δ
x

Check warning on line 229 in src/LogDensityProblems.jl

View check run for this annotation

Codecov / codecov/patch

src/LogDensityProblems.jl#L227-L229

Added lines #L227 - L229 were not covered by tests
end

include("utilities.jl")

end # module
Loading