From 17e8596aae51489fdbd552869f75c0bff20b38a5 Mon Sep 17 00:00:00 2001 From: Nathanael Bosch Date: Mon, 20 Nov 2023 11:58:45 +0100 Subject: [PATCH] Add vale.sh to fix documentation for typos and more (#275) --- .../Vocab/ProbNumDiffEq/accept.txt | 17 +++++++++++++++++ .../Vocab/ProbNumDiffEq/reject.txt | 0 .github/workflows/vale.yml | 17 +++++++++++++++++ .gitignore | 3 +++ .vale.ini | 17 +++++++++++++++++ README.md | 19 +++---------------- benchmarks/lotkavolterra.jmd | 4 ++-- benchmarks/rober.jmd | 2 +- benchmarks/vanderpol.jmd | 2 +- docs/src/benchmarks/lotkavolterra.md | 6 ++---- docs/src/benchmarks/rober.md | 4 +--- docs/src/benchmarks/vanderpol.md | 4 +--- docs/src/diffusions.md | 2 +- docs/src/implementation.md | 16 ++++++++-------- docs/src/initialization.md | 2 +- docs/src/tutorials/dae.md | 6 +++--- docs/src/tutorials/dynamical_odes.md | 2 +- docs/src/tutorials/fenrir.md | 2 +- docs/src/tutorials/getting_started.md | 10 +++++----- justfile | 3 +++ 20 files changed, 88 insertions(+), 50 deletions(-) create mode 100644 .github/vale-styles/Vocab/ProbNumDiffEq/accept.txt create mode 100644 .github/vale-styles/Vocab/ProbNumDiffEq/reject.txt create mode 100644 .github/workflows/vale.yml create mode 100644 .vale.ini diff --git a/.github/vale-styles/Vocab/ProbNumDiffEq/accept.txt b/.github/vale-styles/Vocab/ProbNumDiffEq/accept.txt new file mode 100644 index 000000000..ecd3db334 --- /dev/null +++ b/.github/vale-styles/Vocab/ProbNumDiffEq/accept.txt @@ -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 diff --git a/.github/vale-styles/Vocab/ProbNumDiffEq/reject.txt b/.github/vale-styles/Vocab/ProbNumDiffEq/reject.txt new file mode 100644 index 000000000..e69de29bb diff --git a/.github/workflows/vale.yml b/.github/workflows/vale.yml new file mode 100644 index 000000000..c8e67107d --- /dev/null +++ b/.github/workflows/vale.yml @@ -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 diff --git a/.gitignore b/.gitignore index 23157c00e..4aab4608d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ /benchmarks/.ipynb_checkpoints/ /docs/src/benchmarks/cache/ +.github/vale-styles/* +!.github/vale-styles/Vocab/ProbNumDiffEq + build/ .ob-jupyter/ /.vscode/ diff --git a/.vale.ini b/.vale.ini new file mode 100644 index 000000000..7429c8e8d --- /dev/null +++ b/.vale.ini @@ -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).+?\), \ diff --git a/README.md b/README.md index e41e9a613..a11bdf0a8 100644 --- a/README.md +++ b/README.md @@ -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/) @@ -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 @@ -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 @@ -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). diff --git a/benchmarks/lotkavolterra.jmd b/benchmarks/lotkavolterra.jmd index d5719ed12..33696d142 100644 --- a/benchmarks/lotkavolterra.jmd +++ b/benchmarks/lotkavolterra.jmd @@ -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; @@ -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; diff --git a/benchmarks/rober.jmd b/benchmarks/rober.jmd index b97efab11..18c9b8771 100644 --- a/benchmarks/rober.jmd +++ b/benchmarks/rober.jmd @@ -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; diff --git a/benchmarks/vanderpol.jmd b/benchmarks/vanderpol.jmd index f6992ede9..a885aebe9 100644 --- a/benchmarks/vanderpol.jmd +++ b/benchmarks/vanderpol.jmd @@ -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; diff --git a/docs/src/benchmarks/lotkavolterra.md b/docs/src/benchmarks/lotkavolterra.md index 932edba74..3b5cdddcc 100644 --- a/docs/src/benchmarks/lotkavolterra.md +++ b/docs/src/benchmarks/lotkavolterra.md @@ -40,7 +40,7 @@ plot(test_sol, title="Lotka-Volterra Solution", legend=false) -## EK0 accross orders +## EK0 across orders ```julia DENSE = false; @@ -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; @@ -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` ``` - - diff --git a/docs/src/benchmarks/rober.md b/docs/src/benchmarks/rober.md index 486d60b5a..f39f51419 100644 --- a/docs/src/benchmarks/rober.md +++ b/docs/src/benchmarks/rober.md @@ -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; @@ -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` ``` - - diff --git a/docs/src/benchmarks/vanderpol.md b/docs/src/benchmarks/vanderpol.md index 2fa57f023..7123947f6 100644 --- a/docs/src/benchmarks/vanderpol.md +++ b/docs/src/benchmarks/vanderpol.md @@ -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; @@ -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` ``` - - diff --git a/docs/src/diffusions.md b/docs/src/diffusions.md index 7e5bd8301..65bb0fa67 100644 --- a/docs/src/diffusions.md +++ b/docs/src/diffusions.md @@ -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)``, diff --git a/docs/src/implementation.md b/docs/src/implementation.md index e75008432..3440f09a4 100644 --- a/docs/src/implementation.md +++ b/docs/src/implementation.md @@ -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`. @@ -39,8 +39,8 @@ 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` @@ -48,4 +48,4 @@ ProbNumDiffEq.jl builds around this structure and overloads some of the parts: - 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. diff --git a/docs/src/initialization.md b/docs/src/initialization.md index 9c7392146..f44ea596c 100644 --- a/docs/src/initialization.md +++ b/docs/src/initialization.md @@ -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). diff --git a/docs/src/tutorials/dae.md b/docs/src/tutorials/dae.md index 2e61e4cbf..544df1d0c 100644 --- a/docs/src/tutorials/dae.md +++ b/docs/src/tutorials/dae.md @@ -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 @@ -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)) @@ -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 diff --git a/docs/src/tutorials/dynamical_odes.md b/docs/src/tutorials/dynamical_odes.md index 6dc8db9e0..2204f70e8 100644 --- a/docs/src/tutorials/dynamical_odes.md +++ b/docs/src/tutorials/dynamical_odes.md @@ -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 diff --git a/docs/src/tutorials/fenrir.md b/docs/src/tutorials/fenrir.md index d4f11feca..0a3ae0ec8 100644 --- a/docs/src/tutorials/fenrir.md +++ b/docs/src/tutorials/fenrir.md @@ -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}``. diff --git a/docs/src/tutorials/getting_started.md b/docs/src/tutorials/getting_started.md index ab5fdb8a4..22427e9a2 100644 --- a/docs/src/tutorials/getting_started.md +++ b/docs/src/tutorials/getting_started.md @@ -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 @@ -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] @@ -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. diff --git a/justfile b/justfile index 45a7ed13e..7504c2300 100644 --- a/justfile +++ b/justfile @@ -15,3 +15,6 @@ servedocs-continuously: benchmark: julia --project=benchmarks -e 'include("benchmarks/runall.jl")' + +vale: + vale . \ No newline at end of file