From e7cf7da90f138dbd9fce4b3247dfb3b029cfd6d3 Mon Sep 17 00:00:00 2001 From: Saud Zahir Date: Mon, 30 Mar 2026 17:08:41 +0500 Subject: [PATCH] Refactor documentation formatting and improve installation instructions (#22) --- .github/dependabot.yml | 6 -- docs/api.md | 8 ++- docs/index.md | 116 +++++++++++++---------------------- docs/installation.md | 133 +++++++++++++++++++++++++---------------- docs/quickstart.md | 20 +++---- mkdocs.yml | 16 +++-- 6 files changed, 152 insertions(+), 147 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7e6c742..6a61862 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,9 +6,3 @@ updates: schedule: interval: "weekly" day: "friday" - - - package-ecosystem: "uv" - directory: "/" - schedule: - interval: "weekly" - day: "friday" diff --git a/docs/api.md b/docs/api.md index d7aac02..a6dbfed 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,8 +1,10 @@ # API Reference -All public routines are exported via the `sdepack` Python module. Only -subroutines declared in the `src/sdepack.pyf` interface file are accessible -from Python. +`sdepack` provides a Python interface to a high-performance Fortran numerical +core compiled via `f2py`. All public routines are exported through the +`sdepack` module; only subroutines declared in the `src/sdepack.pyf` +interface file are accessible from Python. See the [Theory](theory.md) and +[Quickstart](quickstart.md) for mathematical background and usage. --- diff --git a/docs/index.md b/docs/index.md index 8b9c309..819b0f8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,76 +4,69 @@ --- -## What is sdepack? +## Overview `sdepack` is a Python library for solving scalar [stochastic differential equations](https://en.wikipedia.org/wiki/Stochastic_differential_equation) -(SDEs) using stochastic Runge-Kutta methods. The numerical core is written in -Fortran and compiled via `f2py`, giving near-native performance while -providing a clean, NumPy-based Python API. +(SDEs) using stochastic Runge-Kutta methods. It allows you to **easily** and **efficiently** +integrate SDEs driven by a Wiener process — from molecular dynamics and population genetics +to option pricing and control systems. -A **stochastic differential equation** is a differential equation in which one -or more terms are stochastic processes, producing a solution that is itself a -random process. SDEs are used to model phenomena across science and engineering -where systems are subject to random influences — from molecular dynamics and -population genetics to option pricing and signal processing. +A **stochastic differential equation** is a differential equation in which one or more terms +are stochastic processes, producing a solution that is itself a random process. `sdepack` targets **scalar Itô SDEs** of the general form: $$ -dX(t) = \underbrace{a(X, t)}_{\text{drift}}\,dt - + \underbrace{b(X, t)}_{\text{diffusion}}\,dW(t), +dX(t) = a(X, t)\,dt + b(X, t)\,dW(t), $$ -where $W(t)$ is a [Wiener process](https://en.wikipedia.org/wiki/Wiener_process) -(standard Brownian motion). - -## Why sdepack? - -| Feature | Detail | -|---|---| -| **Performance** | Compiled Fortran core — no Python loops in the hot path | -| **Reproducibility** | Deterministic seeded RNG (Park-Miller LCG with Schrage's overflow protection) | -| **Range of solvers** | Orders 1–4, covering both time-invariant and time-variant SDEs | -| **Simplicity** | One function call per solve; solutions land in a pre-allocated NumPy array | -| **Portability** | Linux, macOS, Windows; Python 3.10–3.14 | - -## Mathematical model - -Within the solvers, the SDE is parameterized as: - -**Time-invariant** routines integrate +where $W(t)$ is a [Wiener process](https://en.wikipedia.org/wiki/Wiener_process) (standard +Brownian motion). Within the solvers, the SDE is parameterized as: $$ -dX(t) = F(X)\,dt + Q\,G(X)\,dW(t), +dX(t) = F(X, t)\,dt + Q\,G(X, t)\,dW(t), $$ -**Time-variant** routines integrate +where $F$ is the user-supplied **drift** callback, $G$ is the user-supplied **diffusion** +callback, and $Q$ scales the noise intensity. For **time-invariant** routines, $F$ and $G$ +do not depend explicitly on time. -$$ -dX(t) = F(X,t)\,dt + Q\,G(X,t)\,dW(t), -$$ +## Requirements -where $Q$ scales the noise intensity (spectral density of the driving white -noise), $F$ is the user-supplied **drift** callback and $G$ is the -user-supplied **diffusion** callback. +- [NumPy](http://www.numpy.org/) -Integration is performed with a uniform time step: +## Example Usage -$$ -H = \frac{T_N - T_0}{N}. -$$ +```python +import numpy as np +import sdepack -Stage noise for the Runge-Kutta stages is drawn from: +# Ornstein-Uhlenbeck process: dX = -X dt + dW +x = np.zeros(1001, dtype=np.float64) +sdepack.rk4_ti_solve( + lambda x: -x, # drift F(X) = -X + lambda x: 1.0, # diffusion G(X) = 1 + x, + 0.0, # t0 + 10.0, # tn + 1.0, # x0 + 1000, # n steps + 1.0, # Q (noise intensity) + 42, # seed +) +print(x[:6]) +``` -$$ -W_i = Z_i\sqrt{\frac{Q_i Q}{H}},\quad Z_i \sim \mathcal{N}(0,1), -$$ +## Main Features -where $Q_i$ are method-specific noise coefficients that ensure the correct -stochastic scaling at each Runge-Kutta stage. +1. Seven stochastic Runge-Kutta solvers (orders 1–4). +2. Both time-invariant and time-variant SDE forms. +3. Plain Python callables for drift and diffusion — lambdas work too. +4. Seeded, fully reproducible trajectories via a built-in PRNG. +5. NumPy array output — integrates directly with matplotlib, scipy, and the scientific Python stack. -## Available solvers +**Available solvers:** | Solver | Stages | Order | Time-dependence | Based on | |---|---|---|---|---| @@ -85,29 +78,6 @@ stochastic scaling at each Runge-Kutta stage. | `rk4_ti_solve` | 4 | 4 | invariant | Kasdin (1995) | | `rk4_tv_solve` | 4 | 4 | variant | Kasdin (1995) | -!!! tip "Choosing a solver" - For exploratory work, start with `rk1_ti_solve` (Euler-Maruyama). - For production accuracy, prefer `rk4_ti_solve` or `rk4_tv_solve` — higher-order - methods converge faster and yield smoother trajectories for a given step count. - -## Quick example - -```python -import numpy as np -import sdepack +## References -# Ornstein-Uhlenbeck process: dX = -X dt + dW -x = np.zeros(1001, dtype=np.float64) -sdepack.rk4_ti_solve( - lambda x: -x, # drift F(X) = -X - lambda x: 1.0, # diffusion G(X) = 1 - x, - 0.0, # t0 - 10.0, # tn - 1.0, # x0 - 1000, # n steps - 1.0, # Q (noise intensity) - 42, # seed -) -print(x[:6]) # first few values of the trajectory -``` +- N. J. Kasdin, 1995, *Runge-Kutta algorithm for the numerical integration of stochastic differential equations*, Journal of Guidance, Control, and Dynamics, Vol. 18, No. 1, pp. 114–120. diff --git a/docs/installation.md b/docs/installation.md index 227bf6d..17cdf0d 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,61 +1,69 @@ # Installation -`sdepack` is distributed as a compiled wheel on PyPI and can also be installed -from source via GitHub. +`sdepack` can be installed from PyPI, conda-forge, or directly from git. ---- +## [PyPI](https://pypi.org/project/sdepack) -## Prerequisites +For using the PyPI package in your project, you can update your configuration file by adding +the following snippet. -- **Python 3.10+** -- **NumPy** (installed automatically as a dependency) +=== "pyproject.toml" -For source builds you additionally need: + ```toml + [project.dependencies] + sdepack = "*" # (1)! + ``` + + 1. Specifying a version is recommended -- A Fortran compiler (`gfortran` recommended) -- `meson` and `meson-python` build system -- `numpy` (for `f2py` compilation) +=== "requirements.txt" -## PyPI (recommended) + ``` + sdepack>=0.1.0 + ``` ### pip -```bash -pip install --upgrade sdepack -``` +=== "Installation for user" -### pyproject.toml dependency + ```bash + pip install --upgrade --user sdepack # (1)! + ``` -```toml -[project] -dependencies = [ - "sdepack" -] -``` + 1. You may need to use `pip3` instead of `pip` depending on your Python installation. -### requirements.txt +=== "Installation in virtual environment" -```text -sdepack -``` + ```bash + python -m venv .venv + source .venv/bin/activate + pip install --require-virtualenv --upgrade sdepack # (1)! + ``` + + 1. You may need to use `pip3` instead of `pip` depending on your Python installation. + + !!! note + Command to activate the virtual env depends on your platform and shell. [More info](https://docs.python.org/3/library/venv.html#how-venvs-work) + +### pipenv -## Package managers + pipenv install sdepack ### uv -```bash -# Add to a uv project -uv add sdepack +=== "Adding to uv project" -# Or install into the current environment -uv pip install sdepack -``` + ```bash + uv add sdepack + uv sync + ``` -### pipenv +=== "Installing to uv environment" -```bash -pipenv install sdepack -``` + ```bash + uv venv + uv pip install sdepack + ``` ### poetry @@ -75,7 +83,39 @@ pdm add sdepack hatch add sdepack ``` -## Installing from source (GitHub) +## [conda-forge](https://anaconda.org/conda-forge/sdepack) + +You can update your environment spec file by adding the following snippet. + +```yaml title="environment.yml" +channels: + - conda-forge +dependencies: + - pip + - pip: + - sdepack # (1)! +``` + +1. Specifying a version is recommended + +Installation can be done using the updated environment spec file. + +=== "conda" + + ```bash + conda env update --file environment.yml + ``` + +=== "micromamba" + + ```bash + micromamba env update --file environment.yml + ``` + +!!! note + Replace `environment.yml` with your actual environment spec file name if it's different. + +## [git](https://github.com/eggzec/sdepack) Install the latest development version directly from the repository: @@ -83,10 +123,9 @@ Install the latest development version directly from the repository: pip install --upgrade "git+https://github.com/eggzec/sdepack.git#egg=sdepack" ``` -### Building locally +### Building from source -Clone and build from source if you want to modify the Fortran code or test -local changes: +Clone and build from source if you want to modify the Fortran code or test local changes: ```bash git clone https://github.com/eggzec/sdepack.git @@ -94,12 +133,9 @@ cd sdepack pip install -e . ``` -This invokes the `meson` build system to compile the Fortran sources via -`f2py` and install the resulting extension module in development mode. - !!! warning "Fortran compiler required" - Source builds require a working Fortran compiler. On most Linux - distributions install `gfortran`: + Source builds require a working Fortran compiler (`gfortran` recommended) as well as + `meson` and `meson-python`. ```bash # Debian/Ubuntu @@ -129,8 +165,5 @@ print("sdepack is working! Trajectory:", x) ## Dependencies -| Package | Purpose | -|---|---| -| `numpy` | Array handling, `f2py` integration | - -No other runtime dependencies are required. +- Python >= 3.10 +- [numpy](https://pypi.org/project/numpy) diff --git a/docs/quickstart.md b/docs/quickstart.md index 77c70ad..0ee8abd 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -264,16 +264,16 @@ mean 0 and variance $\sigma^2/(2\theta) = 0.125$. !!! tip "Plotting trajectories" Use `matplotlib` with the time grid for visualization: - ```python - import matplotlib.pyplot as plt - - t = np.linspace(0.0, tn, N + 1) - plt.plot(t, x) - plt.xlabel("Time") - plt.ylabel("X(t)") - plt.title("SDE trajectory") - plt.show() - ``` +```python +import matplotlib.pyplot as plt + +t = np.linspace(0.0, tn, N + 1) +plt.plot(t, x) +plt.xlabel("Time") +plt.ylabel("X(t)") +plt.title("SDE trajectory") +plt.show() +``` !!! tip "Seed selection" The seed must be a positive integer. Different seeds produce entirely diff --git a/mkdocs.yml b/mkdocs.yml index b350b33..ad64787 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,15 +17,21 @@ theme: - content.code.copy markdown_extensions: - - admonition + - attr_list + - md_in_html - tables - - fenced_code + - toc: + permalink: true + title: Page contents + - admonition + - pymdownx.details - pymdownx.superfences - - pymdownx.highlight + - pymdownx.highlight: + pygments_lang_class: true + - pymdownx.tabbed: + alternate_style: true - pymdownx.arithmatex: generic: true - - toc: - permalink: true extra_javascript: - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js