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
8 changes: 2 additions & 6 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,20 @@ version = "1.1.3"

[compat]
AllocCheck = "0.2"
Aqua = "0.8"
JET = "0.9, 0.10, 0.11"
LinearAlgebra = "1.10"
SafeTestsets = "0.1"
SciMLTesting = "2.1"
SciMLTesting = "2.4"
Statistics = "1.10"
Test = "1.10"
julia = "1.10"

[extras]
AllocCheck = "9b6a8646-10ed-4001-bbdc-1d2f46dfbb1a"
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f"
SciMLTesting = "09d9d899-5365-40a9-917a-5f67fddea283"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["AllocCheck", "Aqua", "JET", "LinearAlgebra", "SafeTestsets", "SciMLTesting", "Statistics", "Test"]
test = ["AllocCheck", "LinearAlgebra", "SafeTestsets", "SciMLTesting", "Statistics", "Test"]
8 changes: 3 additions & 5 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ DocMeta.setdocmeta!(
:(using SurrogatesBase)
)

cp("./docs/Manifest.toml", "./docs/src/assets/Manifest.toml", force = true)
cp("./docs/Project.toml", "./docs/src/assets/Project.toml", force = true)

pages = [
"Home" => "index.md",
"interface.md",
"api.md",
"Developer Interface" => "interface.md",
"Public API" => "api.md",
]

ENV["GKSwstype"] = "100"
Expand All @@ -21,6 +18,7 @@ makedocs(
modules = [SurrogatesBase],
sitename = "SurrogatesBase.jl",
clean = true,
checkdocs = :exports,
doctest = true,
linkcheck = true,
format = Documenter.HTML(
Expand Down
3 changes: 2 additions & 1 deletion docs/src/api.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# API
# Public API

```@docs
SurrogatesBase
SurrogatesBase.AbstractDeterministicSurrogate
SurrogatesBase.AbstractStochasticSurrogate
SurrogatesBase.update!
Expand Down
60 changes: 1 addition & 59 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Pkg.add("SurrogatesBase")
## Contributing

- Please refer to the
[SciML ColPrac: Contributor's Guide on Collaborative Practices for Community Packages](https://github.com/SciML/ColPrac/blob/master/README.md)
[SciML ColPrac: Contributor's Guide on Collaborative Practices for Community Packages](https://docs.sciml.ai/ColPrac/stable/)
for guidance on PRs, issues, and other matters relating to contributing to SciML.

- See the [SciML Style Guide](https://github.com/SciML/SciMLStyle) for common coding practices and other style decisions.
Expand All @@ -36,61 +36,3 @@ Pkg.add("SurrogatesBase")
[Julia Zulip](https://julialang.zulipchat.com/#narrow/stream/279055-sciml-bridged)
+ On the [Julia Discourse forums](https://discourse.julialang.org)
+ See also [SciML Community page](https://sciml.ai/community/)

## Reproducibility

```@raw html
<details><summary>The documentation of this SciML package was built using these direct dependencies,</summary>
```

```@example
using Pkg # hide
Pkg.status() # hide
```

```@raw html
</details>
```

```@raw html
<details><summary>and using this machine and Julia version.</summary>
```

```@example
using InteractiveUtils # hide
versioninfo() # hide
```

```@raw html
</details>
```

```@raw html
<details><summary>A more complete overview of all dependencies and their versions is also provided.</summary>
```

```@example
using Pkg # hide
Pkg.status(; mode = PKGMODE_MANIFEST) # hide
```

```@raw html
</details>
```

```@eval
using TOML
using Markdown
version = TOML.parse(read("../../Project.toml", String))["version"]
name = TOML.parse(read("../../Project.toml", String))["name"]
link_manifest = "https://github.com/SciML/" * name * ".jl/tree/gh-pages/v" * version *
"/assets/Manifest.toml"
link_project = "https://github.com/SciML/" * name * ".jl/tree/gh-pages/v" * version *
"/assets/Project.toml"
Markdown.parse("""You can also download the
[manifest]($link_manifest)
file and the
[project]($link_project)
file.
""")
```
146 changes: 49 additions & 97 deletions docs/src/interface.md
Original file line number Diff line number Diff line change
@@ -1,128 +1,80 @@
# The SurrogateBase Interface
# Extending SurrogatesBase

## Deterministic Surrogates

Deterministic surrogates `s` are subtypes of `SurrogatesBase.AbstractDeterministicSurrogate`,
which is a subtype of `Function`.

### Required methods

The method `update!(s, xs, ys)` **must** be implemented and the surrogate **must** be
[callable](https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects)
`s(xs)`, where `xs` is a `Vector` of input points and `ys` is a `Vector` of corresponding evaluations.
SurrogatesBase defines the small public contract shared by deterministic and stochastic surrogate
packages. It supplies interface tags and generic functions only; concrete packages own fitting,
evaluation, posterior representations, and data storage.

Calling `update!(s, xs, ys)` refits the surrogate `s` to include evaluations `ys` at points `xs`.
The result of `s(xs)` is a `Vector` of evaluations of the surrogate at points `xs`, corresponding to approximations of the underlying function at points `xs` respectively.

For single points `x` and `y`, call these methods via `update!(s, [x], [y])`
and `s([x])`.
## Deterministic Surrogates

### Optional methods
A deterministic implementation subtypes [`AbstractDeterministicSurrogate`](@ref) and is callable.
The minimum interface is:

If the surrogate `s` wants to expose current parameter values, the method `parameters(s)` **must** be implemented.
```julia
(surrogate)(x)
update!(surrogate, new_x, new_y)
```

If the surrogate `s` has tunable hyperparameters, the methods
`update_hyperparameters!(s, prior)` and `hyperparameters(s)` **must** be implemented.
`x` can be a scalar, one point, or a batch, according to the concrete package's documented domain.
The base interface does not impose a container representation. A batch call must preserve the
correspondence between its inputs and predictions.

Calling `update_hyperparameters!(s, prior)` updates the hyperparameters of the surrogate `s` by performing hyperparameter optimization using the information in `prior`. After the hyperparameters of `s` are updated, `s` is fit to past evaluations.
Calling `hyperparameters(s)` returns current values of hyperparameters.
`update!` is in place. `new_x` and `new_y` represent matching observations: a batch has the same
number of locations and values in the same order, and a scalar update represents exactly one pair.
Implementations may return `nothing`, the updated surrogate, or another implementation-specific
value. Generic code must inspect the mutated surrogate instead of relying on that return value.

### Example
An implementation may additionally expose [`parameters`](@ref), [`hyperparameters`](@ref), and
[`update_hyperparameters!`](@ref). These are optional, so consumers should only call them when a
concrete surrogate documents support.

```julia
using SurrogatesBase

struct RBF{T} <: AbstractDeterministicSurrogate
scale::T
centers::Vector{T}
weights::Vector{T}
mutable struct LinearMock <: AbstractDeterministicSurrogate
slope::Float64
end

(rbf::RBF)(xs) = [rbf.weights' * exp.(-rbf.scale * (x .- rbf.centers).^2)
for x in xs]
(surrogate::LinearMock)(x) = surrogate.slope * x

function SurrogatesBase.update!(rbf::RBF, xs, ys)
# Refit the surrogate by updating rbf.weights to include new
# evaluations ys at points xs
return rbf
end

SurrogatesBase.parameters(rbf::RBF) = rbf.centers, rbf.weights

SurrogatesBase.hyperparameters(rbf::RBF) = rbf.scale

function SurrogatesBase.update_hyperparameters!(rbf::RBF, prior)
# update rbf.scale and fit the surrogate by adapting rbf.weights
return rbf
function SurrogatesBase.update!(surrogate::LinearMock, new_x, new_y)
surrogate.slope = last(new_y) / last(new_x)
return nothing
end
```

## Stochastic Surrogates

Stochastic surrogates `s` are subtypes of `SurrogatesBase.AbstractStochasticSurrogate`.

### Required methods

The methods `update!(s, xs, ys)` and `finite_posterior(s, xs)` **must** be implemented, where `xs` is a `Vector` of input points and `ys` is a `Vector` of corresponding observed samples.

Calling `update!(s, xs, ys)` refits the surrogate `s` to include observations `ys` at points `xs`.

For single points `x` and `y`, call the `update!(s, xs, ys)` via `update!(s, [x], [y])`.

Calling `finite_posterior(s, xs)` returns an object that provides methods for working with the finite
dimensional posterior distribution at points `xs`.
The following methods might be supported:

- `mean(finite_posterior(s,xs))` returns a `Vector` of posterior means at `xs`
- `var(finite_posterior(s,xs))` returns a `Vector` of posterior variances at `xs`
- `mean_and_var(finite_posterior(s,xs))` returns a `Tuple` consisting of a `Vector` of posterior means and a `Vector` of posterior variances at `xs`
- `rand(finite_posterior(s,xs))` returns a `Vector`, which is a sample from the joint posterior at points `xs`

### Optional methods

If the surrogate `s` wants to expose current parameter values, the method `parameters(s)` **must** be implemented.

If the surrogate `s` has tunable hyper-parameters, the methods
`update_hyperparameters!(s, prior)` and `hyperparameters(s)` **must** be implemented.

Calling `update_hyperparameters!(s, prior)` updates the hyperparameters of the surrogate `s` by performing hyperparameter optimization using the information in `prior`. After the hyperparameters of `s` are updated, `s` is fit to past samples.
Calling `hyperparameters(s)` returns current values of hyperparameters.
A stochastic implementation subtypes [`AbstractStochasticSurrogate`](@ref) and implements:

```julia
update!(surrogate, new_x, new_y)
finite_posterior(surrogate, xs)
```

### Example
The update rules are the same as for deterministic surrogates. `finite_posterior` receives query
inputs in a concrete implementation's documented representation and returns that implementation's
finite-dimensional posterior object. That object must preserve the query ordering and document the
operations it supports, such as `Statistics.mean`, `Statistics.var`, or `rand`.

```julia
using Statistics
using SurrogatesBase

mutable struct GaussianProcessSurrogate{D, R, GP, H <: NamedTuple} <: AbstractStochasticSurrogate
xs::Vector{D}
ys::Vector{R}
gp_process::GP
hyperparameters::H
mutable struct ConstantPosteriorSurrogate <: AbstractStochasticSurrogate
mean_value::Float64
end

function SurrogatesBase.update!(g::GaussianProcessSurrogate, new_xs, new_ys)
append!(g.xs, new_xs)
append!(g.ys, new_ys)
# condition the prior `g.gp_process` on new data to obtain a posterior
# update g.gp_process to the posterior process
return g
struct ConstantPosterior
means::Vector{Float64}
end

function SurrogatesBase.finite_posterior(g::GaussianProcessSurrogate, xs)
# Return a finite dimensional projection of g.gp_process at points xs.
# The returned object GP_finite supports methods mean(GP_finite) and
# var(GP_finite) for obtaining the vector of means and variances at points xs.
end
Statistics.mean(posterior::ConstantPosterior) = posterior.means

SurrogatesBase.hyperparameters(g::GaussianProcessSurrogate) = g.hyperparameters

function SurrogatesBase.update_hyperparameters!(g::GaussianProcessSurrogate, prior)
# Use prior on hyperparameters, e.g., parameters uniformly distributed
# between an upper and lower bound, to perform hyperparameter optimization.
# Set g.hyperparameters to the improved hyperparameters.
# Fit a Gaussian process that uses the updated hyperparameters to past
# samples and save it in g.gp_process.
return g
function SurrogatesBase.finite_posterior(surrogate::ConstantPosteriorSurrogate, xs)
return ConstantPosterior(fill(surrogate.mean_value, length(xs)))
end
```
```

The package test suite validates these rules using mock subtypes that are driven only through the
public SurrogatesBase functions. This keeps the extension contract independent of implementation
details from any concrete surrogate package.
Loading
Loading