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
33 changes: 11 additions & 22 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.26.0.dev3] - 2026-10-14

### Added

- Added `benchmarks/hierarchical_profile.py`, which shows where the time of a `VariationalBayes` fit goes and counts the objective evaluations per participant and iteration; against cbm (RLRW, 100 participants, 120 trials), cpm makes about as many evaluations but each one costs more, at 17.3 against 5.0 ms per participant and iteration
- Added a `hessian` argument to `cpm.optimisation.FminBound`, `Fmin`, `Minimize` and `Bads`; `hessian="finite_differences"` computes the Hessian at the optimum with bounded finite differences (`cpm.core.optimisers.finite_difference_hessian`), cutting Hessian evaluations from 22 to 7 per participant and iteration in the speed comparison. The default, `"numdifftools"`, keeps the previous Hessian
- Added a `start` argument to `cpm.hierarchical.EmpiricalBayes` and `cpm.hierarchical.VariationalBayes`; `start="prior_mean"` starts the first optimisation of every participant from the current prior's location, clipped into the bounds, as cbm does, so fits stop sooner. The default, `"random"`, keeps the previous starts
- Added a `positive_definite` column to the `fit` of `cpm.hierarchical.EmpiricalBayes` and `cpm.hierarchical.VariationalBayes`, recording whether each participant's Hessian was positive definite, and a `not_positive_definite` column to their `hyperparameters` with the count; an estimate on a bound can have a non-positive-definite Hessian and is kept, as the bounds require
- Added the results of the speed comparison with cbm (100 participants, 120 trials) in `benchmarks/results/hierarchical-comparison-*.csv`: combining `hessian="finite_differences"`, `start="prior_mean"` and `number_of_starts=1` brings `EmpiricalBayes`/`VariationalBayes` from 20.8/20.1 to 6.8/7.0 ms per participant and iteration, against cbm's 4.4 ms, with RMSE against 0.26.0.dev1 staying within bootstrap 95% intervals throughout

### Changed

- `cpm.optimisation.FminBound` with `approx_grad=True` now computes the finite-difference gradient itself, together with the objective, exactly as SciPy does, with identical results; with `LogLikelihood.bernoulli`, this makes the hierarchical fits of the speed comparison 19% faster
- The defaults of the new arguments, `hessian="numdifftools"` and `start="random"`, give the same results as before for the same seed; the faster options have to be chosen

### Fixed

- Fixed fits with `parallel=True` and `prior=True` going back to the priors the model was created with after the first evaluation in every worker, so that priors updated with `update_prior`, such as the population priors of `cpm.hierarchical.EmpiricalBayes` and `cpm.hierarchical.VariationalBayes`, were ignored; parallel fits now equal serial ones, and parallel results with updated priors change. `cpm.generators` no longer deletes its submodules, which made dill copy its classes into the workers instead of referencing them
- Fixed `Fmin`, `FminBound`, `Minimize` and `Bads` comparing every later start with the first instead of the best so far, which with three or more starts could replace a participant's best fit with a worse one; results with three or more starts can change
- Fixed the `cpm.hierarchical.VariationalBayes` docstring giving 1000 as the default of `iteration`, which is 50

## [0.26.0.dev2] - 2026-10-06
## [0.26.0] - 2026-10-16

### Added

Expand All @@ -51,6 +30,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added test units for `SessionWrapper`, `cpm.models.kernels`, the fast priors, and the built-in applications with and without numba
- Added a benchmark suite (`benchmarks/run.py` for one evaluation, `benchmarks/hierarchical.py` for the hierarchical tutorials) and `scripts/local_tests.py`, which runs the tests with and without numba
- Added a GitHub Actions workflow that runs the tests with and without numba, on Python 3.11 to 3.14
- Added `benchmarks/hierarchical_profile.py`, which shows where the time of a `VariationalBayes` fit goes and counts the objective evaluations per participant and iteration; against cbm (RLRW, 100 participants, 120 trials), cpm makes about as many evaluations but each one costs more, at 17.3 against 5.0 ms per participant and iteration
- Added a `hessian` argument to `cpm.optimisation.FminBound`, `Fmin`, `Minimize` and `Bads`; `hessian="finite_differences"` computes the Hessian at the optimum with bounded finite differences (`cpm.core.optimisers.finite_difference_hessian`), cutting Hessian evaluations from 22 to 7 per participant and iteration in the speed comparison. The default, `"numdifftools"`, keeps the previous Hessian
- Added a `start` argument to `cpm.hierarchical.EmpiricalBayes` and `cpm.hierarchical.VariationalBayes`; `start="prior_mean"` starts the first optimisation of every participant from the current prior's location, clipped into the bounds, as cbm does, so fits stop sooner. The default, `"random"`, keeps the previous starts
- Added a `positive_definite` column to the `fit` of `cpm.hierarchical.EmpiricalBayes` and `cpm.hierarchical.VariationalBayes`, recording whether each participant's Hessian was positive definite, and a `not_positive_definite` column to their `hyperparameters` with the count; an estimate on a bound can have a non-positive-definite Hessian and is kept, as the bounds require
- Added the results of the speed comparison with cbm (100 participants, 120 trials) in `benchmarks/results/hierarchical-comparison-*.csv`: combining `hessian="finite_differences"`, `start="prior_mean"` and `number_of_starts=1` brings `EmpiricalBayes`/`VariationalBayes` from 20.8/20.1 to 6.8/7.0 ms per participant and iteration, against cbm's 4.4 ms, with RMSE against 0.26.0.dev1 staying within bootstrap 95% intervals throughout

### Changed

Expand All @@ -70,6 +54,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `cpm.models.activation.ProspectUtility.weights` and `.utilities` are float arrays instead of object arrays, and the `simulation` records of `HybridMBMF` hold NumPy scalars instead of Python numbers
- `PTSM2025` always uses its power utility: replacing `parameters.utility_curvature` on a model no longer changes it
- Required Python 3.11 or later (previously `>3.11.0`, which excluded 3.11.0), removed the PyPy classifier, and tagged the wheel for Python 3 only
- `cpm.optimisation.FminBound` with `approx_grad=True` now computes the finite-difference gradient itself, together with the objective, exactly as SciPy does, with identical results; with `LogLikelihood.bernoulli`, this makes the hierarchical fits of the speed comparison 19% faster
- The defaults of the new arguments, `hessian="numdifftools"` and `start="random"`, give the same results as before for the same seed; the faster options have to be chosen

### Fixed

Expand Down Expand Up @@ -101,6 +87,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed a clean install raising `ModuleNotFoundError` in `diagnostics()`, by adding `matplotlib` to the dependencies
- Fixed `cpm.utils.data` and `cpm.utils.metad` not being reachable after `import cpm`
- Fixed `cpm.core.diagnostics.gelman_rubin` and `cpm.core.diagnostics.psrf` failing on every call, and `gelman_rubin` computing the statistic incorrectly
- Fixed fits with `parallel=True` and `prior=True` going back to the priors the model was created with after the first evaluation in every worker, so that priors updated with `update_prior`, such as the population priors of `cpm.hierarchical.EmpiricalBayes` and `cpm.hierarchical.VariationalBayes`, were ignored; parallel fits now equal serial ones, and parallel results with updated priors change. `cpm.generators` no longer deletes its submodules, which made dill copy its classes into the workers instead of referencing them
- Fixed `Fmin`, `FminBound`, `Minimize` and `Bads` comparing every later start with the first instead of the best so far, which with three or more starts could replace a participant's best fit with a worse one; results with three or more starts can change
- Fixed the `cpm.hierarchical.VariationalBayes` docstring giving 1000 as the default of `iteration`, which is 50

## [0.25.6] - 2026-04-15

Expand Down
15 changes: 11 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,11 +209,18 @@ Best ways to get help:

## Build and release notes

If you are preparing a release artifact:
To prepare a release:

```bash
python setup.py sdist bdist_wheel
```
1. Set the version in `cpm/__version__.py` and date its section in `CHANGELOG.md`.
2. Build and check the source distribution and wheel:

```bash
pip install build twine
python -m build
twine check dist/*
```

3. After merging into `main`, tag the release with the bare version (for example `0.26.0`, not `v0.26.0`); the documentation links to the source at this tag.

Publishing to PyPI is maintainer-only and typically done with:

Expand Down
8 changes: 4 additions & 4 deletions LICENSES-BUNDLE
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ The cpm repository and source distributions bundle a number of libraries that
are compatibly licensed. We list these here.

Name: metadpy
Files: cpm/application/signal_detection.py
Files: cpm/applications/signal_detection.py
License: GPLv3
For details, see header comments in cpm/application/signal_detection.py.
For details, see header comments in cpm/applications/signal_detection.py.

Name: meta-d MATLAB scripts
Files: cpm/applications/signal_detection.py
License: None
For details, see header comments in cpm/application/signal_detection.py.
For details, see header comments in cpm/applications/signal_detection.py.
The MATLAB scripts are not included in the cpm repository, but are
referenced in the cpm/application/signal_detection.py file.
referenced in the cpm/applications/signal_detection.py file.
The MATLAB scripts are available at <https://www.columbia.edu/~bsm2105/type2sdt/>
and were written by Brian Maniscalco. There is no accompanying license
information, but they are still referenced here for completeness.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ python -m sphinx -b html docs docs/_build/html
```

Then open `docs/_build/html/index.html` in a browser.
See [CONTRIBUTING.md](CONTRIBUTING.md) for how to write documentation and tutorials, and for a live preview while you write.
See [CONTRIBUTING.md](https://github.com/DevComPsy/cpm/blob/main/CONTRIBUTING.md) for how to write documentation and tutorials, and for a live preview while you write.

The documentation is published to GitHub Pages by the `docs` GitHub Actions workflow whenever `main` changes.

Expand Down
2 changes: 1 addition & 1 deletion cpm/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.26.0.dev3"
__version__ = "0.26.0"
2 changes: 1 addition & 1 deletion docs/news/2026-09-faster-fitting.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ kernelspec:

# Faster fitting in cpm 0.26

*28 September 2026 · cpm 0.26.0, in development*
*28 September 2026 · cpm 0.26.0*

The built-in models of cpm now compute all trials of a participant in one call instead of one call per trial, and, when [numba](https://numba.pydata.org/) is installed, that loop over trials is compiled.
Fitting them is 90 to 220 times faster than in cpm 0.25, and more than 1,000 times faster for {py:class}`~cpm.applications.decision_making.PTSM2025`, with the same results.
Expand Down
18 changes: 14 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[build-system]
requires = [
"setuptools>=61.0",
"setuptools>=77.0",
]
build-backend = "setuptools.build_meta"

Expand All @@ -20,15 +20,22 @@ authors = [
maintainers = [
{ name = "Lenard Dome", email = "lenarddome@gmail.com" }
]
license = { text = "AGPLv3" }
license = "AGPL-3.0-only"
license-files = ["LICENSE", "LICENSES-BUNDLE"]
requires-python = ">=3.11"
keywords = ["cpm-toolbox", "cpm", "computational-psychiatry", "computational-psychology", "psychometrics", "psychology"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Affero General Public License v3",
"Intended Audience :: Science/Research",
"Natural Language :: English",
"Programming Language :: Python :: 3"
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Topic :: Scientific/Engineering"
]
dependencies = [
"numpy>=2.0.0",
Expand Down Expand Up @@ -78,6 +85,9 @@ notebooks = [
[project.urls]
Homepage = "https://cpm-toolbox.net"
Documentation = "https://devcompsy.github.io/cpm/"
Repository = "https://github.com/DevComPsy/cpm"
Issues = "https://github.com/DevComPsy/cpm/issues"
Changelog = "https://github.com/DevComPsy/cpm/blob/main/CHANGELOG.md"

[tool.setuptools]
include-package-data = true
Expand Down
Loading