diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d2ac1ecf..537f1d39 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -230,6 +230,7 @@ Choose the prefix that best describes the change: | `MAINT` | Refactor or maintain code without changing intended behavior | | `TST` | Add or improve tests | | `DOC` | Update documentation | +| `JOSS` | Update the JOSS paper or its submission materials | | `BLD` | Change packaging, dependencies, or build configuration | | `CI` | Change continuous integration workflows | | `REL` | Prepare or maintain a release | diff --git a/joss_paper/Makefile b/joss_paper/Makefile new file mode 100644 index 00000000..77310faa --- /dev/null +++ b/joss_paper/Makefile @@ -0,0 +1,30 @@ +.PHONY: joss arxiv arxiv.pdf + +# Build the JOSS PDF without the abstract (default). +joss: + docker run --rm \ + --volume "$(CURDIR):/data" \ + --user "$$(id -u):$$(id -g)" \ + --env JOURNAL=joss \ + openjournals/inara \ + -o pdf -- paper.md --metadata=abstract: + +# Build the arXiv preprint. +arxiv: + docker run --rm \ + --volume "$(CURDIR):/data" \ + --user "$$(id -u):$$(id -g)" \ + --env JOURNAL=joss \ + openjournals/inara \ + -o preprint paper.md + +# Compile the arXiv preprint to paper.preprint.pdf. +arxiv.pdf: arxiv + docker run --rm \ + --volume "$(CURDIR):/data" \ + --user "$$(id -u):$$(id -g)" \ + --workdir /data \ + --env XDG_CACHE_HOME=/tmp \ + --entrypoint latexmk \ + openjournals/inara \ + -xelatex -interaction=nonstopmode -halt-on-error paper.preprint.tex diff --git a/joss_paper/paper.bib b/joss_paper/paper.bib new file mode 100644 index 00000000..ae71bb4f --- /dev/null +++ b/joss_paper/paper.bib @@ -0,0 +1,222 @@ +@book{chopin2020introduction, + title={An introduction to sequential {Monte Carlo}}, + author={Chopin, Nicolas and Papaspiliopoulos, Omiros}, + series={Springer Series in Statistics}, + year={2020}, + publisher={Springer}, + doi={10.1007/978-3-030-47845-2} +} + +@article{delmoral2006smc, + title={Sequential {Monte Carlo} Samplers}, + author={Del Moral, Pierre and Doucet, Arnaud and Jasra, Ajay}, + journal={Journal of the Royal Statistical Society: Series B (Statistical Methodology)}, + volume={68}, + number={3}, + pages={411--436}, + year={2006}, + doi={10.1111/j.1467-9868.2006.00553.x} +} + +@article{karamanis2025persistent, + title={Persistent Sampling: Enhancing the Efficiency of Sequential {Monte Carlo}}, + author={Karamanis, Minas and Seljak, Uro{\v{s}}}, + journal={Statistics and Computing}, + volume={35}, + number={5}, + pages={144}, + year={2025}, + publisher={Springer}, + doi={10.1007/s11222-025-10682-y} +} + +@article{cabezas2024blackjax, + title={{BlackJAX}: Composable {Bayesian} inference in {JAX}}, + author={Cabezas, Alberto and Corenflos, Adrien and Lao, Junpeng and Louf, R{\'e}mi and Carnec, Antoine and Chaudhari, Kaustubh and Cohn-Gordon, Reuben and Coullon, Jeremie and Deng, Wei and Duffield, Sam and Dur{\'a}n-Mart{\'i}n, Gerardo and Elantkowski, Marcin and Foreman-Mackey, Dan and Gregori, Michele and Iguaran, Carlos and Kumar, Ravin and Lysy, Martin and Murphy, Kevin and Orduz, Juan Camilo and Patel, Karm and Wang, Xi and Zinkov, Rob}, + journal={arXiv preprint arXiv:2402.10797}, + url={https://arxiv.org/abs/2402.10797}, + year={2024} +} + +@article{demasi2026sharpy, + title={The Sequential {Monte Carlo} goes {NUTS}: Boosting Gravitational-Wave Inference}, + author={Demasi, Gabriele and Capurri, Giulia and Lenti, Massimo and Ricciardone, Angelo and Patricelli, Barbara and Frattale Mascioli, Adriano and Piccari, Lorenzo and Albuquerque, Saulo and Guidi, Gianluca M. and Pannarale, Francesco and Stratta, Giulia and Del Pozzo, Walter}, + journal={arXiv preprint arXiv:2601.02336}, + url={https://arxiv.org/abs/2601.02336}, + year={2026} +} + +@article{ashton2019bilby, + title={{Bilby}: A user-friendly {Bayesian} inference library for gravitational-wave astronomy}, + author={Ashton, Gregory and H{\"u}bner, Moritz and Lasky, Paul D. and Talbot, Colm and Ackley, Kendall and Biscoveanu, Sylvia and Chu, Qi and Divarkala, Atul and Easter, Paul J. and Goncharov, Boris and Hernandez Vivanco, Francisco and Harms, Jan and Lower, Marcus E. and Meadors, Grant D. and Melchor, Denyz and Payne, Ethan and Pitkin, Matthew D. and Powell, Jade and Sarin, Nikhil and Smith, Rory J. E. and Thrane, Eric}, + journal={The Astrophysical Journal Supplement Series}, + volume={241}, + number={2}, + pages={27}, + year={2019}, + doi={10.3847/1538-4365/ab06fc} +} + +@article{abrilpla2023pymc, + title={{PyMC}: A modern, and comprehensive probabilistic programming framework in {Python}}, + author={Abril-Pla, Oriol and Andreani, Virgile and Carroll, Colin and Dong, Larry and Fonnesbeck, Christopher J. and Kochurov, Maxim and Kumar, Ravin and Lao, Junpeng and Luhmann, Christian C. and Martin, Osvaldo A. and Osthege, Michael and Vieira, Ricardo and Wiecki, Thomas V. and Zinkov, Robert}, + journal={PeerJ Computer Science}, + volume={9}, + pages={e1516}, + year={2023}, + doi={10.7717/peerj-cs.1516} +} + +@misc{smcpy_repo, + author = {{NASA Langley Research Center}}, + title = {{SMCPy}: {Python} module for uncertainty quantification using a parallel sequential {Monte Carlo} sampler}, + year = {2026}, + howpublished = {\url{https://github.com/nasa/SMCPy}}, + note = {Accessed 2026-07-07} +} + +@misc{python_array_api, + author = {{Consortium for Python Data API Standards}}, + title = {{Python} array {API} standard}, + year = {2026}, + howpublished = {\url{https://data-apis.org/array-api/latest/}}, + note = {Accessed 2026-07-07} +} + +@article{williams2026accelerated, + author = "Williams, Michael J.", + title = "{Accelerated Sequential Posterior Inference via Reuse for Gravitational-Wave Analyses}", + eprint = "2511.04218", + archivePrefix = "arXiv", + primaryClass = "hep-ex", + reportNumber = "LIGO-P2500623", + doi = "10.1103/5hvn-3lmh", + journal = "Physical Review Letters", + volume = "137", + number = "2", + pages = "021410", + year = "2026" +} + + +@article{salomone2025unbiased, + author = {Salomone, Robert and South, Leah F and Drovandi, Christopher and Kroese, Dirk P and Johansen, Adam M}, + title = {Unbiased and consistent nested sampling via sequential {Monte Carlo}}, + journal = {Journal of the Royal Statistical Society Series B: Statistical Methodology}, + volume = {87}, + number = {4}, + pages = {1221--1238}, + year = {2025}, + month = {09}, + issn = {1369-7412}, + doi = {10.1093/jrsssb/qkaf015}, + url = {https://doi.org/10.1093/jrsssb/qkaf015}, + eprint = {https://academic.oup.com/jrsssb/article-pdf/87/4/1221/63166567/qkaf015.pdf}, +} + +@article{dau2022wastefree, + author = {Dau, Hai-Dang and Chopin, Nicolas}, + title = {Waste-Free Sequential {Monte Carlo}}, + journal = {Journal of the Royal Statistical Society Series B: Statistical Methodology}, + volume = {84}, + number = {1}, + pages = {114--148}, + year = {2022}, + month = {02}, + issn = {1369-7412}, + doi = {10.1111/rssb.12475}, + url = {https://doi.org/10.1111/rssb.12475}, + eprint = {https://academic.oup.com/jrsssb/article-pdf/84/1/114/49324223/jrsssb_84_1_114.pdf}, +} + +@misc{williams2026inprep, + author = {Williams, Michael J. and Chapman-Bird, Christian E. A. and Costa Barroso, Raissa and Harry, Ian}, + title = {Robust {Bayesian} inference for massive black hole binaries in {LISA} with sequential {Monte Carlo}}, + howpublished = {Manuscript in preparation (provisional title)}, + year = {2026} +} + +@software{sequince, + author = {Michael J. Williams and + Christian Chapman-Bird}, + title = {{sequince-dev/sequince}}, + year = {2026}, + publisher = {Zenodo}, + doi = {10.5281/zenodo.23596103}, + url = {https://doi.org/10.5281/zenodo.23596103}, +} + +@software{sequince_density, + author = {Michael J. Williams}, + title = {{sequince-dev/sequince-density}}, + year = {2026}, + publisher = {Zenodo}, + doi = {10.5281/zenodo.23687687}, + url = {https://doi.org/10.5281/zenodo.23687687}, +} + +@software{sequince_bilby, + author = {Michael J. Williams}, + title = {{sequince-dev/sequince-bilby}}, + year = {2026}, + publisher = {Zenodo}, + doi = {10.5281/zenodo.23736054}, + url = {https://doi.org/10.5281/zenodo.23736054}, +} + +@misc{sequince_examples, + author = {{Sequince contributors}}, + title = {{sequince-dev/sequince-examples}}, + year = {2026}, + url = {https://github.com/sequince-dev/sequince-examples}, + note = {Accessed 2026-10-27}, +} + +@software{orng, + author = {Michael J. Williams and + Colm Talbot}, + title = {{sequince-dev/orng}}, + year = {2026}, + publisher = {Zenodo}, + doi = {10.5281/zenodo.17544786}, + url = {https://doi.org/10.5281/zenodo.17544786}, +} + +@software{bilby, + author = {Colm Talbot and + Gregory Ashton and + Moritz Hübner and + Matt Pitkin and + Michael J. Williams and + plasky and + asb5468 and + Aditya Vijaykumar and + Rory Smith and + SMorisaki and + John Veitch and + Duncan Macleod and + Nikhil Sarin and + Daniel Williams and + JasperMartins and + MarcArene and + Vivien Raymond and + C P L Berry and + AlexandreGoettel and + Fabian Gittins and + Ceciliogq and + Lorenzo Pompili and + Ivan Markin and + David Keitel and + Hen42rik and + Mick Wright and + oliviawilk and + noahewolfe and + jacobgolomb and + Shichao Wu}, + title = {{bilby-dev/bilby}}, + month = aug, + year = 2026, + publisher = {Zenodo}, + doi = {10.5281/zenodo.14025463}, + url = {https://doi.org/10.5281/zenodo.14025463}, +} diff --git a/joss_paper/paper.md b/joss_paper/paper.md new file mode 100644 index 00000000..3ba9f888 --- /dev/null +++ b/joss_paper/paper.md @@ -0,0 +1,123 @@ +--- +title: 'Sequince: a modular sequential Monte Carlo toolkit' +tags: + - Python + - Bayesian inference + - Sequential Monte Carlo + - Particle filtering +authors: +- name: Michael J. Williams + orcid: 0000-0003-2198-2974 + affiliation: "1, 2" +- name: Christian E. A. Chapman-Bird + orcid: 0000-0002-2728-9612 + affiliation: 3 +affiliations: +- name: Max Planck Institute for Gravitational Physics (Albert Einstein Institute), Am Mühlenberg 1, 14476 Potsdam, Germany + index: 1 +- name: Institute of Cosmology and Gravitation, University of Portsmouth, United Kingdom + index: 2 +- name: Institute for Gravitational Wave Astronomy, University of Birmingham, United Kingdom + index: 3 +date: '\today' +bibliography: paper.bib +abstract: | + Sequential Monte Carlo (SMC) methods approximate sequences of probability distributions using populations of weighted samples and are widely applicable, including in Bayesian inference and particle filtering. We present `sequince`, a modular Python toolkit for constructing SMC algorithms from reusable and extensible components. The toolkit provides modular steps for weighting, resampling, mutation, transformation, and control operations that are composed to implement different algorithms. It also includes prebuilt samplers for tempered SMC, persistent sampling and nested sampling via SMC. Its core components follow the Python Array API standard, supporting NumPy, JAX, PyTorch, and CuPy, enabling analyses on CPUs or GPUs. Random-number control and checkpointing support reproducible scientific workflows. This paper describes `sequince` v0.1.0 and its design as reusable infrastructure for methodological research and application of SMC methods. +--- + +# Summary + +Sequential Monte Carlo (SMC) methods are a flexible family of algorithms for +approximating sequences of probability distributions using a population of weighted samples, known as particles +[@delmoral2006smc; @chopin2020introduction]. +Such sequences arise naturally in applications including Bayesian inference +and particle filtering, for example through likelihood tempering or observations arriving over time. + +`sequince` [@sequince] is a Python toolkit for constructing SMC methods from reusable and extensible +components. This paper describes `sequince` v0.1.0. +The toolkit provides abstractions for defining sequences of target +distributions and for composing the operations used to evolve a particle population between them. +These include weighting, resampling, mutation, and control steps. +It is designed for researchers developing new SMC methods or adapting existing methods to scientific applications, including astrophysical inference, with checkpointing to support long-running analyses. Its core components follow the Python Array API standard, supporting NumPy, JAX, PyTorch, and CuPy arrays and enabling compatible workflows to run on CPUs or GPUs. + +# Statement of need + +Scientific applications often require SMC methods tailored to a particular problem. Researchers may need to combine adaptive tempering, mutation kernels, transformations, stopping rules, or multi-stage procedures, and to define problem-specific sequences of target distributions. When this logic is embedded in application-specific code, it becomes harder to compare methods, reuse components, and move prototype algorithms into stable analysis software. + +`sequince` addresses these needs through a general-purpose, step-oriented framework with interchangeable algorithmic components. Researchers can start from pre-built samplers for common inference problems or construct custom pipelines with explicit control over the operations and their execution order. The same framework therefore supports both established inference methods and methodological research into new SMC variants. + +Scientific models are also increasingly implemented using different numerical libraries to exploit automatic differentiation and hardware acceleration. Coupling an SMC implementation to a single array library can restrict its integration with these models. `sequince` uses the Python Array API standard [@python_array_api] to support reusable core operations across multiple numerical backends, while allowing specialised components to target particular ecosystems. + +# State of the field + +The Python ecosystem already contains several useful SMC-related tools. The `particles` package accompanying @chopin2020introduction provides implementations of many established SMC and particle-filtering methods and is particularly useful for teaching and methodological prototyping. `SMCPy` focuses on uncertainty quantification and Bayesian calibration using parallel likelihood-tempering SMC samplers, including fixed and adaptive tempering variants [@smcpy_repo]. `pocomc` implements persistent sampling with normalizing flows for posterior inference [@karamanis2025persistent]. + +Broader Bayesian software ecosystems also expose SMC functionality. `PyMC` includes a sequential Monte Carlo sampler within a general probabilistic programming framework [@abrilpla2023pymc], while `BlackJAX` provides composable inference components in the JAX ecosystem and includes SMC methods alongside other Monte Carlo algorithms [@cabezas2024blackjax]. Recent domain-specific frameworks such as SHARPy target gravitational-wave inference with JAX-accelerated SMC and gradient-based mutation kernels [@demasi2026sharpy]. + +`sequince` combines support for multiple SMC variants, including tempering, persistent sampling [@karamanis2025persistent], nested sampling via SMC (NS-SMC) [@salomone2025unbiased], and waste-free SMC [@dau2022wastefree], with a modular architecture for constructing bespoke algorithms. Shared interfaces allow users to reconfigure target sequences, transformations, mutation kernels, and control flow, supporting both the comparison of existing methods and the development of new variants. Support for multiple array backends and integrations with different sampling ecosystems further enable these components to be reused across scientific applications and numerical libraries. The need to combine configurable target sequences, independently reusable steps, and multiple array backends within one framework motivated this design. This combination makes `sequince` useful as research infrastructure for methodological work and as a foundation for application-specific downstream packages. + +# Software design + +`sequince` separates target distributions, particle populations, and the operations used to evolve them. The following outlines the main design choices; the [documentation](https://sequince.readthedocs.io/en/latest/) and [runnable examples](https://sequince.readthedocs.io/projects/sequince-examples/en/latest/) provide detailed descriptions of the interfaces and their use. + +The distributions approximated during an SMC run are represented by target objects. A target evaluates named components of a probability distribution for a population of particles, while sequential targets describe how that distribution changes between stages. Separating the target from the operations that evolve the particles allows weighting and mutation components to be reused across different inference procedures. For example, tempered SMC and nested-sampling SMC use different target sequences while sharing resampling and compatible mutation components. + +Target evaluations are stored as particle-aligned collections of named quantities. These can be propagated through resampling and updated during mutation, allowing previously computed quantities to be reused where valid. This is particularly useful for scientific applications in which likelihood evaluations dominate the computational cost. A `ParticleState` stores the particles, their log weights, accumulated normalising-constant information, and associated target evaluations. Specialised states provide additional information where required, such as the archive of previous populations used by persistent SMC. + +An SMC algorithm is expressed as an ordered collection of steps. Each step receives the current particle state, a runtime context, and a random number generator, and returns an updated state, updated context, and structured outputs. Weighting, resampling, mutation, transformation, and control operations can therefore be implemented independently and combined into different algorithms. Higher-level steps can conditionally execute or compose other steps, keeping algorithm-specific control flow outside the runner. For example, waste-free SMC combines resampling with a mutation component that retains intermediate chain states. + +A `SequentialMonteCarlo` runner repeatedly applies the configured steps. The runtime context contains the current iteration and observation, shared user-provided information, metadata used for communication between steps, and stopping controls. The runner accepts an iterable of observations, supporting both static inference problems and procedures in which targets change as new data become available. Separating particle state, runtime context, and algorithm configuration allows the execution machinery to remain common across different SMC constructions. + +Each step can return structured outputs containing quantities such as effective sample sizes, tempering parameters, acceptance statistics, and other diagnostics. These outputs and the recorded particle states are collected in an `SMCResult` for subsequent analysis. New components can therefore introduce diagnostics without requiring changes to the runner or coupling their implementation to plotting and logging code. Callbacks provide logging, plotting, and other monitoring functionality during execution. + +The core abstractions follow the Python Array API standard where possible [@python_array_api], allowing backend-native arrays to pass through the SMC procedure. Random number generation is similarly abstracted through `orng` [@orng]. This design supports reuse across numerical libraries while allowing specialised components to depend on a particular ecosystem. Alongside conventional eager execution, `sequince` provides a functional execution path that passes random state explicitly between steps. Compatible iterations can be compiled using facilities such as `jax.jit`, provided their operations are traceable and their state structures, shapes, and dtypes remain stable, while the runner manages observations, callbacks, and result recording. Mutation integrations include ecosystem-specific packages such as `BlackJAX` [@cabezas2024blackjax]. + +Checkpointing is separate from result recording. Checkpoints capture the particle state, runtime progress, random-number state, and mutable step state needed to continue sampling with a reconstructed sampler configuration. Results provide the analysis record of a completed or partially completed run. Both support HDF5 storage, making numerical data and supported metadata available for inspection independently of the running process. + +# Research impact statement + +`sequince` is being developed as reusable infrastructure for both +methodological research and problem-specific inference workflows. Current +applications include customised sampling strategies for astrophysical inference +problems relevant to ongoing LIGO-Virgo-KAGRA analyses and future observations +with the Laser Interferometer Space Antenna (LISA) [@williams2026inprep], as well as integration with +broader Bayesian inference ecosystems such as `bilby` [@ashton2019bilby; @bilby] via `sequince-bilby` [@sequince_bilby]. The +same methodology is also relevant to future ground-based observatories such as +the Einstein Telescope (ET) and Cosmic Explorer (CE). + +In these applications, the principal benefit of `sequince` is not a single +sampling algorithm but a shared framework in which new sequential inference +methods can be implemented, compared, and reused. The package has been used to +explore alternative tempering strategies, persistent SMC, specialised mutation +schemes, problem-specific transformations, and hardware-accelerated execution. +The common result interface also provides a consistent way to record and +compare algorithm-specific diagnostics across these different methods. + +The modular design of `sequince` additionally supports downstream packages that +add method- or domain-specific functionality without requiring those +dependencies in the core library. For example, `sequince-density` [@sequince_density] provides +density-estimation components based on Gaussian mixture models and normalizing +flows. These can be combined with the core SMC machinery for learned +preconditioning, proposal construction, and other density-assisted SMC methods, +including approaches related to `pocomc` and `aspire` [@karamanis2025persistent; +@williams2026accelerated]. The wider sequince ecosystem also includes +`sequince-examples`, which provides runnable examples demonstrating common +workflows and more specialised uses of the package [@sequince_examples], with +[online documentation](https://sequince.readthedocs.io/projects/sequince-examples/en/latest/). + +# AI usage disclosure + +Generative AI tools, including OpenAI Codex, were used to assist with code implementation and refactoring. ChatGPT was also used to assist with the organisation and editing of the manuscript. Models varied over the course of development and included GPT-5.3, GPT-5.4, GPT-5.6, GPT-6.0, and GPT-6.1; a complete historical record of model versions was not retained. The authors made the core scientific and software design decisions and reviewed, edited, and validated all AI-assisted contributions. The authors retain full responsibility for the software and manuscript. + +# Acknowledgements + +M.J.W. acknowledges partial support from the UKSA's LISA Ground Segment (UKRI968) and Science and Technology Facilities Council (STFC) grant UKRI2490. +C.E.A.C-B. is supported by UKSA grant UKRI971. + +Numerical computations were carried out on the SCIAMA high-performance +computing cluster, which is supported by the Institute of Cosmology and +Gravitation and the University of Portsmouth. Additional computations were +performed using the University of Birmingham's BlueBEAR High Performance +Computing facility. + +# References diff --git a/tests/test_commit_message.py b/tests/test_commit_message.py index c0b19936..c0f09ce1 100644 --- a/tests/test_commit_message.py +++ b/tests/test_commit_message.py @@ -22,6 +22,10 @@ "REL(packaging): prepare release artifacts", "REL/DOC: prepare release notes", "DOC/REL: update release notes", + "JOSS: update paper", + "JOSS(paper): add bibliography entries", + "JOSS/DOC: update paper instructions", + "DOC/JOSS: clarify paper build commands", "BUG/TST: correct weights", "BUG/TST(smc): reject degenerate weights", "MAINT/PERF(resampling): avoid duplicate reductions", @@ -52,6 +56,7 @@ def test_accepts_valid_subject( "", "FIX: correct weights", "bug: correct weights", + "joss: update paper", "BUG(SMC): correct weights", "BUG(): correct weights", "BUG(smc extra): correct weights", diff --git a/tools/check_commit_message.py b/tools/check_commit_message.py index 55b1ab42..2cbffe2b 100644 --- a/tools/check_commit_message.py +++ b/tools/check_commit_message.py @@ -5,7 +5,7 @@ import sys from pathlib import Path -PREFIX_PATTERN = r"(?:BUG|ENH|PERF|API|DEP|MAINT|TST|DOC|BLD|CI|STY|REL)" +PREFIX_PATTERN = r"(?:BUG|ENH|PERF|API|DEP|MAINT|TST|DOC|BLD|CI|STY|REL|JOSS)" SUBJECT_PATTERN = re.compile( rf"{PREFIX_PATTERN}(?:/{PREFIX_PATTERN})?" r"(?:\([a-z][a-z0-9_.-]*\))?: [a-z][^\r\n]*" @@ -46,7 +46,8 @@ def main() -> int: "Expected PREFIX(scope): lowercase summary, or PREFIX: lowercase " "summary.\n" "Two prefixes may be joined with '/', e.g. BUG/TST(smc): fix weights\n" - "Prefixes: BUG, ENH, PERF, API, DEP, MAINT, TST, DOC, BLD, CI, STY, REL.\n" + "Prefixes: BUG, ENH, PERF, API, DEP, MAINT, TST, DOC, BLD, CI, STY, " + "REL, JOSS.\n" "Optional scopes start with a lowercase letter and contain only " "lowercase letters, digits, '.', '_', or '-'.\n" "Use a single-line subject without trailing whitespace or a period.\n"