Skip to content

Commit

Permalink
Add vale.sh to fix documentation for typos and more (#275)
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanaelbosch authored Nov 20, 2023
1 parent 7e9b963 commit 17e8596
Show file tree
Hide file tree
Showing 20 changed files with 88 additions and 50 deletions.
17 changes: 17 additions & 0 deletions .github/vale-styles/Vocab/ProbNumDiffEq/accept.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Hennig
Tronarp
Kersting
Schober
[Nn]umerics
probdiffeq
ProbNumDiffEq\.jl
interpolant
postamble
API(s)
Kalman
timestepping
DAE(s)
runtime(s)
diffusion(s)
[a posteriori]
linearize
Empty file.
17 changes: 17 additions & 0 deletions .github/workflows/vale.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: vale.sh

on:
push:
branches:
- 'main'
- 'release-'
tags: '*'
pull_request:

jobs:
vale:
name: runner / vale
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: errata-ai/vale-action@reviewdog
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/benchmarks/.ipynb_checkpoints/
/docs/src/benchmarks/cache/

.github/vale-styles/*
!.github/vale-styles/Vocab/ProbNumDiffEq

build/
.ob-jupyter/
/.vscode/
Expand Down
17 changes: 17 additions & 0 deletions .vale.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
StylesPath = .github/vale-styles
MinAlertLevel = error
Vocab = ProbNumDiffEq

Packages = Google, write-good

[formats]
jmd = md

[*.md]
BasedOnStyles = Vale, Google, write-good
Google.Exclamation = warning
Google.Slang = warning
Google.Quotes = Nowarning
TokenIgnores = \
\$.+?\$, \
\]\(@(ref|id|cite).+?\), \
19 changes: 3 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ProbNumDiffEq.jl

[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://nathanaelbosch.github.io/ProbNumDiffEq.jl/stable)
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://nathanaelbosch.github.io/ProbNumDiffEq.jl/dev)
[![Development](https://img.shields.io/badge/docs-dev-blue.svg)](https://nathanaelbosch.github.io/ProbNumDiffEq.jl/dev)
[![Build Status](https://github.com/nathanaelbosch/ProbNumDiffEq.jl/workflows/CI/badge.svg)](https://github.com/nathanaelbosch/ProbNumDiffEq.jl/actions)
[![Coverage](https://codecov.io/gh/nathanaelbosch/ProbNumDiffEq.jl/branch/main/graph/badge.svg?token=eufIemCGXn)](https://codecov.io/gh/nathanaelbosch/ProbNumDiffEq.jl)
[![Benchmarks](http://img.shields.io/badge/benchmarks-docs-blueviolet.svg)](https://nathanaelbosch.github.io/ProbNumDiffEq.jl/dev/benchmarks/multi-language-wrappers/)
Expand All @@ -14,7 +14,7 @@ __ProbNumDiffEq.jl__ provides _probabilistic numerical_ ODE solvers to the
[DifferentialEquations.jl](https://diffeq.sciml.ai/stable/) ecosystem.
The implemented _ODE filters_ solve differential equations via Bayesian filtering and smoothing. The filters compute not just a single point estimate of the true solution, but a posterior distribution that contains an estimate of its numerical approximation error.

For a short intro video, check out our [poster presentation at JuliaCon2021](https://www.youtube.com/watch?v=EMFl6ytP3iQ).
For a short intro video, check out the [ProbNumDiffEq.jl poster presentation at JuliaCon2021](https://www.youtube.com/watch?v=EMFl6ytP3iQ).


## Installation
Expand Down Expand Up @@ -53,7 +53,7 @@ plot(sol, color=["#CB3C33" "#389826" "#9558B2"])

![Fitzhugh-Nagumo Solution](./examples/fitzhughnagumo.svg?raw=true "Fitzhugh-Nagumo Solution")

Since we're doing probabilistic numerics the solution also contains error estimates, it just happens that they are too small to be visible in the plot above.
In probabilistic numerics, the solution also contains error estimates - it just happens that they are too small to be visible in the plot above.
But we can just plot them directly:

```julia
Expand All @@ -71,16 +71,3 @@ plot(sol.t, hcat(stds...)', color=["#CB3C33" "#389826" "#9558B2"]
- [probdiffeq](https://pnkraemer.github.io/probdiffeq/): Fast and feature-rich filtering-based probabilistic ODE solvers in JAX.
- [ProbNum](https://probnum.readthedocs.io/en/latest/): Probabilistic numerics in Python. It has not only probabilistic ODE solvers, but also probabilistic linear solvers, Bayesian quadrature, and many filtering and smoothing implementations.
- [Fenrir.jl](https://github.com/nathanaelbosch/Fenrir.jl): Parameter-inference in ODEs with probabilistic ODE solvers. This package builds on ProbNumDiffEq.jl to provide a negative marginal log-likelihood function, which can then be used with an optimizer or with MCMC for parameter inference.


## References

The main references _for this package_ include:

- M. Schober, S. Särkkä, and P. Hennig: **A Probabilistic Model for the Numerical Solution of Initial Value Problems** (2018) ([link](https://link.springer.com/article/10.1007/s11222-017-9798-7))
- F. Tronarp, H. Kersting, S. Särkkä, and P. Hennig: **Probabilistic Solutions To Ordinary Differential Equations As Non-Linear Bayesian Filtering: A New Perspective** (2019) ([link](https://link.springer.com/article/10.1007/s11222-019-09900-1))
- N. Krämer, P. Hennig: **Stable Implementation of Probabilistic ODE Solvers** (2020) ([link](https://arxiv.org/abs/2012.10106))
- N. Bosch, P. Hennig, F. Tronarp: **Calibrated Adaptive Probabilistic ODE Solvers** (2021) ([link](http://proceedings.mlr.press/v130/bosch21a.html))
- N. Bosch, F. Tronarp, P. Hennig: **Pick-and-Mix Information Operators for Probabilistic ODE Solvers** (2022) ([link](https://proceedings.mlr.press/v151/bosch22a.html))

A more extensive list of references relevant to ODE filters is provided [here](https://nathanaelbosch.github.io/ProbNumDiffEq.jl/stable/references).
4 changes: 2 additions & 2 deletions benchmarks/lotkavolterra.jmd
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test_sol = solve(prob, Vern7(), abstol=1/10^14, reltol=1/10^14, dense=false)
plot(test_sol, title="Lotka-Volterra Solution", legend=false)
```

## EK0 accross orders
## EK0 across orders

```julia
DENSE = false;
Expand Down Expand Up @@ -66,7 +66,7 @@ wp = WorkPrecisionSet(
plot(wp, palette=Plots.palette([:blue, :red], length(_setups)), xticks = 10.0 .^ (-16:1:5))
```

## EK1 accross orders
## EK1 across orders

```julia
DENSE = false;
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/rober.jmd
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ ref_sol = solve(daeprob,IDA(),abstol=1/10^14,reltol=1/10^14,dense=false)
plot(ref_sol, idxs=[y₁,y₂,y₃], title="ROBER Solution", legend=false, ylims=(0, 1))
```

## EK1 accross orders
## EK1 across orders

```julia
DENSE = false;
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/vanderpol.jmd
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ test_sol = solve(prob, RadauIIA5(), abstol=1/10^14, reltol=1/10^14, dense=false)
plot(test_sol, title="Van der Pol Solution", legend=false, ylims=(-2.5, 2.5))
```

## EK1 accross orders
## EK1 across orders

```julia
DENSE = false;
Expand Down
6 changes: 2 additions & 4 deletions docs/src/benchmarks/lotkavolterra.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ plot(test_sol, title="Lotka-Volterra Solution", legend=false)



## EK0 accross orders
## EK0 across orders

```julia
DENSE = false;
Expand Down Expand Up @@ -77,7 +77,7 @@ plot(wp, palette=Plots.palette([:blue, :red], length(_setups)), xticks = 10.0 .^



## EK1 accross orders
## EK1 across orders

```julia
DENSE = false;
Expand Down Expand Up @@ -723,5 +723,3 @@ Info Packages marked with ⌃ and ⌅ have new versions available, but those wi
th ⌅ are restricted by compatibility constraints from upgrading. To see why
use `status --outdated -m`
```


4 changes: 1 addition & 3 deletions docs/src/benchmarks/rober.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ plot(ref_sol, idxs=[y₁,y₂,y₃], title="ROBER Solution", legend=false, ylims



## EK1 accross orders
## EK1 across orders

```julia
DENSE = false;
Expand Down Expand Up @@ -557,5 +557,3 @@ Info Packages marked with ⌃ and ⌅ have new versions available, but those wi
th ⌅ are restricted by compatibility constraints from upgrading. To see why
use `status --outdated -m`
```


4 changes: 1 addition & 3 deletions docs/src/benchmarks/vanderpol.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ plot(test_sol, title="Van der Pol Solution", legend=false, ylims=(-2.5, 2.5))



## EK1 accross orders
## EK1 across orders

```julia
DENSE = false;
Expand Down Expand Up @@ -696,5 +696,3 @@ Info Packages marked with ⌃ and ⌅ have new versions available, but those wi
th ⌅ are restricted by compatibility constraints from upgrading. To see why
use `status --outdated -m`
```


2 changes: 1 addition & 1 deletion docs/src/diffusions.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ and for info on the initial distribution ``\textcolor{purple}{ \mathcal{N} \left
We call ``\textcolor{#4063D8}{\Gamma}`` the _"diffusion"_ parameter.
Since it is typically not known we need to estimate it; this is called _"calibration"_.

There are a few different choices for how to model and estimate ``\textcolor{#4063D8}{\Gamma}``:
ProbNumDiffEq.jl provides a few different choices for how to model and estimate ``\textcolor{#4063D8}{\Gamma}``:
- [`FixedDiffusion`](@ref) assumes an isotropic, time-fixed ``\textcolor{#4063D8}{\Gamma} = \sigma \cdot I_d``,
- [`DynamicDiffusion`](@ref) assumes an isotropic, time-varying ``\textcolor{#4063D8}{\Gamma}(t) = \sigma(t) \cdot I_d`` (**recommended**),
- [`FixedMVDiffusion`](@ref) assumes a diagonal, time-fixed ``\textcolor{#4063D8}{\Gamma} = \operatorname{diag}(\sigma_1, \dots, \sigma_d)``,
Expand Down
16 changes: 8 additions & 8 deletions docs/src/implementation.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ ProbNumDiffEq.jl builds around this structure and overloads some of the parts:

- **Algorithms:** `EK0/EK1 <: AbstractEK <: OrdinaryDiffEq.OrdinaryDiffEqAdaptiveAlgorithm`
- `./src/algorithms.jl` provides the algorithms themselves
- `./src/alg_utils.jl` implements many traits (e.g. relating to autodiff, implicitness, step-size control)
- `./src/alg_utils.jl` implements many traits (relating to automatic differentiation, implicitness, step-size control, etc)
- **Cache:** `EKCache <: AbstractODEFilterCache <: OrdinaryDiffEq.OrdinaryDiffEqCache`
- `./src/caches.jl` implements the cache and its main constructor: `OrdinaryDiffEq.alg_cache`
- **Initialization and `perform_step!`:** via `OrdinaryDiffEq.initialize!` and `OrdinaryDiffEq.perform_step!`.
- **Initialization and `perform_step!`:** via `OrdinaryDiffEq.initialize!` and `OrdinaryDiffEq.perform_step!`.
Implemented in `./src/perform_step.jl`.
- **Custom postamble** by overloading `OrdinaryDiffEq.postamble!` (which should always call `OrdinaryDiffEq._postamble!`).
This is where we do the "smoothing" of the solution.
Implemented in `./src/integrator_utils.jl`.
- **Custom saving** by overloading `OrdinaryDiffEq.savevalues!` (which should always call `OrdinaryDiffEq._savevalues!`).
This is where we do the "smoothing" of the solution.
Implemented in `./src/integrator_utils.jl`.
- **Custom saving** by overloading `OrdinaryDiffEq.savevalues!` (which should always call `OrdinaryDiffEq._savevalues!`).
Implemented in `./src/integrator_utils.jl`.


Expand All @@ -39,13 +39,13 @@ ProbNumDiffEq.jl builds around this structure and overloads some of the parts:
- **`DiffEqBase.__init`** is currently overloaded to transform OOP problems into IIP problems (in `./src/solve.jl`).
- **The solution object:** `ProbODESolution <: AbstractProbODESolution <: DiffEqBase.AbstractODESolution`
- `./src/solution.jl` implements the main parts.
Note that the main constructor `DiffEqBase.build_solution` is called by `OrdinaryDiffEq.__init` - so OrdinaryDiffEq.jl has control over its inputs.
- There is also `MeanProbODESolution <: DiffEqBase.AbstractODESolution`: It allows handling the mean of a probabilistic ODE solution the same way one would handle any "standard" ODE solution - e.g. it is compatible with `DiffEqDevTools.appxtrue`.
Note that the main constructor `DiffEqBase.build_solution` is called by `OrdinaryDiffEq.__init`, so OrdinaryDiffEq.jl has control over its inputs.
- `MeanProbODESolution <: DiffEqBase.AbstractODESolution` is a wrapper that allows handling the mean of a probabilistic ODE solution the same way one would handle any "standard" ODE solution, by just ignoring the covariances.
- `AbstractODEFilterPosterior <: DiffEqBase.AbstractDiffEqInterpolation` is the current interpolant, but it does not actually fully handle the interpolation right now. This part might be subject to change soon.
- *Plot recipe* in `./src/solution_plotting.jl`
- *Sampling* in `./src/solution_sampling.jl`
- `DiffEqBase.prepare_alg(::EK1{0})`; closely follows a similar function implemented in OrdinaryDiffEq.jl `./src/alg_utils.jl`
- this also required `DiffEqBase.remake(::EK1)`

## Other packages
- `DiffEqDevTools.appxtrue` is overloaded to work with `ProbODESolution` (by just doing `mean(sol)`). This also enables `DiffEqDevTools.WorkPrecision` to work out of th box.
- `DiffEqDevTools.appxtrue`: We overload this function to work with `ProbODESolution`. This also enables `DiffEqDevTools.WorkPrecision` to work out of the box.
2 changes: 1 addition & 1 deletion docs/src/initialization.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Y^{(1)}(0) &= f(y_0, 0).
```
It turns out that we can also compute higher-order derivatives of ``y`` with the chain rule,
and then use these to better initialize ``Y^{(i)}(0)``.
This, done efficiently with Taylor-mode autodiff by using
This, done efficiently with Taylor-mode automatic differentiation by using
[TaylorIntegration.jl](https://perezhz.github.io/TaylorIntegration.jl/latest/),
is what [`TaylorModeInit`](@ref) does.
See also [[1]](@ref initrefs).
Expand Down
6 changes: 3 additions & 3 deletions docs/src/tutorials/dae.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ solve(pendulum_prob, Rodas4())
```

It does not work!
This is because of the _index_ of the DAE; see e.g. [this explenation from the tutorial](https://docs.sciml.ai/ModelingToolkit/stable/examples/modelingtoolkitize_index_reduction/#Understanding-DAE-Index).
This is because of the _index_ of the DAE; see for example [this explanation from the tutorial](https://docs.sciml.ai/ModelingToolkit/stable/examples/modelingtoolkitize_index_reduction/#Understanding-DAE-Index).

Does this also hold for the `EK1` solver? Let's find out:
```@example dae
Expand All @@ -107,7 +107,7 @@ traced_sys = modelingtoolkitize(pendulum_prob)
```
(how cool is this latex output ?!?)

Next, lower the DAE index and simplify it with MTK's `dae_index_lowering` and `structural_simplify`:
Next, lower the DAE index and simplify it with ModelingToolkit's `dae_index_lowering` and `structural_simplify`:

```@example dae
simplified_sys = structural_simplify(dae_index_lowering(traced_sys))
Expand All @@ -131,7 +131,7 @@ sol3_f_evals = sol3.stats.nf
```

The error for the index-1 DAE solve is _much_ lower.
So it seems that, even if the index-3 DAE could also be solved directly, index lowering might still be beneficial when solving DAEs with the `EK1`!
Thus it seems that, even if the index-3 DAE could also be solved directly, index lowering might still be beneficial when solving DAEs with the `EK1`!


### References
Expand Down
2 changes: 1 addition & 1 deletion docs/src/tutorials/dynamical_odes.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ E(dx, dy, x, y) = PotentialEnergy(x, y) + KineticEnergy(dx, dy)
E(u) = E(u...); # convenient shorthand
```

So, let's have a look at how the total energy changes over time when we numerically simulate the Hénon-Heiles model over a long period of time:
Let's have a look at how the total energy changes over time when we numerically simulate the Hénon-Heiles model over a long period of time:
Standard solve

```@example dyn
Expand Down
2 changes: 1 addition & 1 deletion docs/src/tutorials/fenrir.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ odedata = [true_sol(t) .+ sqrt(observation_noise_var) * randn(length(u0)) for t
plot(true_sol, color=:black, linestyle=:dash, label=["True Solution" ""])
scatter!(times, stack(odedata), markersize=2, markerstrokewidth=0.1, color=1, label=["Noisy Data" ""])
```
Our goal is then to recover the true parameter `p` (and thus also the true trajectoy plotted above) the noisy data.
Our goal is then to recover the true parameter `p` (and thus also the true trajectory plotted above) the noisy data.

## Computing the negative log-likelihood
To do parameter inference - be it maximum-likelihod, maximum a posteriori, or full Bayesian inference with MCMC - we need to evaluate the likelihood of given a parameter estimate ``\theta_\text{est}``.
Expand Down
10 changes: 5 additions & 5 deletions docs/src/tutorials/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ In this tutorial we solve a simple non-linear ordinary differential equation (OD
If you never used DifferentialEquations.jl, check out their
["Getting Started with Differential Equations in Julia" tutorial](https://docs.sciml.ai/DiffEqDocs/stable/getting_started/).
It explains how to define and solve ODE problems and how to analyze the solution, so it's a great starting point.
Most of ProbNumDiffEq.jl works exaclty as you would expect from DifferentialEquations.jl -- just with some added uncertainties and related functionality on top!
Most of ProbNumDiffEq.jl works exactly as you would expect from DifferentialEquations.jl -- just with some added uncertainties and related functionality on top!


In this tutorial, we consider a
Expand Down Expand Up @@ -126,9 +126,9 @@ plot!(sol.t, zero(errors), ribbon=3error_estimates, label="error estimate",

### More about the `ProbabilisticODESolution`

The solution object returned by ProbNumDiffEq.jl mostly behaves just like any other ODESolution in DifferentialEquations.jl --
The solution object returned by ProbNumDiffEq.jl mostly behaves just like any other `ODESolution` in DifferentialEquations.jl --
with some added uncertainties and related functionality on top.
So, `sol` can be indexed
The `ProbabilisticODESolution` can be indexed

```@repl 1
sol[1]
Expand Down Expand Up @@ -183,5 +183,5 @@ mean(sol(0.45))
## Next steps

Check out one of the other tutorials:
- "[Second Order ODEs and Energy Preservation](@ref)" explains how to solve second-order ODEs more efficiently while also better perserving energy or other conserved quantities;
- "[Solving DAEs with Probabilistic Numerics](@ref)" demonstrates how to solve differential algebraic equatios in a probabilistic numerical way.
- "[Second Order ODEs and Energy Preservation](@ref)" explains how to solve second-order ODEs more efficiently while also better preserving energy or other conserved quantities;
- "[Solving DAEs with Probabilistic Numerics](@ref)" demonstrates how to solve differential algebraic equations in a probabilistic numerical way.
3 changes: 3 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ servedocs-continuously:

benchmark:
julia --project=benchmarks -e 'include("benchmarks/runall.jl")'

vale:
vale .

0 comments on commit 17e8596

Please sign in to comment.