Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fe320fd
docs: add SECURITY.md with reporting process and incident note
Hananel-Hazan Sep 2, 2026
9a99a8e
Merge branch 'master' into hananel
Hananel-Hazan Sep 6, 2026
06ffc8b
perf: fuse STDP updates, drop per-step identity matrices, cache MSTDP…
Hananel-Hazan Sep 6, 2026
60f95c6
validate learning rules against their source papers
Hananel-Hazan Sep 6, 2026
3baf31c
fix: clamp/unclamp spikes now enter the spike traces; document rule s…
Hananel-Hazan Sep 6, 2026
1718455
learning: add Diehl & Cook (2015) rule, drop dt factor from MCC PostP…
Hananel-Hazan Sep 6, 2026
f2d61ce
fix: MSTDP reset must tolerate state that is not built yet
Hananel-Hazan Sep 7, 2026
fca8ee9
Merge master into hananel
Hananel-Hazan Sep 7, 2026
4a3d861
learning: give DiehlAndCook the same documented reset as Hebbian
Hananel-Hazan Sep 7, 2026
a6d1e32
Merge master into hananel
Hananel-Hazan Sep 7, 2026
56ef5d4
ci: restrict GITHUB_TOKEN to contents:read in all workflows
Hananel-Hazan Sep 11, 2026
68715b3
security: document pickle risk in load(); fix three broken torch.load…
Hananel-Hazan Sep 15, 2026
569f8cf
Merge remote-tracking branch 'origin/master' into hananel
Hananel-Hazan Sep 16, 2026
ff7b5af
release: publish 0.3.4 to PyPI
Hananel-Hazan Sep 16, 2026
77beb10
ci+packaging: fix CI-only test failures, Poetry 2.4.3, [project] meta…
Hananel-Hazan Sep 16, 2026
878dc91
docs: record CPU-dependent rounding of the fused addmm_ path
Hananel-Hazan Sep 16, 2026
e2b3df9
Merge remote-tracking branch 'origin/master' into hananel
Hananel-Hazan Sep 16, 2026
2a0a841
docs+ci: make the API reference build, consolidate CI, fix outdated R…
Hananel-Hazan Sep 16, 2026
a80ac93
cleanup: apply isort and enforce it; untrack test logs, launch.json, …
Hananel-Hazan Sep 16, 2026
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
18 changes: 13 additions & 5 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ updates:
- "minor"
- "patch"
ignore:
# torch and torchvision are pinned to exact versions served from the
# custom CUDA wheel index declared in pyproject.toml, and the two must
# move together. Routine version bumps here would break that pairing or
# silently pull the plain PyPI build instead, so they are upgraded by
# hand. These conditions cover version updates only; Dependabot security
# torch and torchvision are locked (poetry.lock) to builds from the CUDA
# wheel index declared in pyproject.toml, and docs/requirements.txt pins
# the matching CPU builds. The two must move together, and a routine bump
# could pull the plain PyPI build instead, so they are upgraded by hand. These conditions cover version updates only; Dependabot security
# alerts for torch and torchvision still come through.
- dependency-name: "torch"
update-types:
Expand Down Expand Up @@ -53,3 +52,12 @@ updates:
github-actions:
patterns:
- "*"

# Base image of the Dockerfile.
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
labels:
- "dependencies"
24 changes: 22 additions & 2 deletions .github/workflows/black.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
# Formatting and import-order check. Branch protection on master requires the job named "lint"; keep that name.
name: Black Formater

on: [push, pull_request]
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
- uses: psf/black@stable
with:
python-version: "3.13"
# Use the black and isort versions pinned in poetry.lock, so CI and local
# formatting agree.
- name: Check formatting with black
run: |
version=$(python -c "import tomllib; print(next(p['version'] for p in tomllib.load(open('poetry.lock','rb'))['package'] if p['name']=='black'))")
pipx run "black==${version}" --check --diff .
- name: Check import order with isort
run: |
version=$(python -c "import tomllib; print(next(p['version'] for p in tomllib.load(open('poetry.lock','rb'))['package'] if p['name']=='isort'))")
pipx run "isort==${version}" --check-only --diff .
64 changes: 38 additions & 26 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
@@ -1,46 +1,58 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

# Tests. Branch protection on master requires the job named "build"; keep that name.
name: BindsNET build status

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
POETRY_VERSION: "2.4.3"

jobs:
build:

name: build
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v7
- name: Set up Python 3.13
uses: actions/setup-python@v7
- name: Install Poetry
run: pipx install "poetry==${POETRY_VERSION}"
- uses: actions/setup-python@v7
with:
python-version: 3.13
python-version: "3.13"
cache: poetry
- name: Install dependencies
run: poetry install
- name: Lint with flake8 (syntax errors and undefined names)
run: pipx run flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
- name: Test with pytest
run: poetry run pytest

# The other supported Python versions (pyproject.toml: >=3.11,<3.14).
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]
steps:
- uses: actions/checkout@v7
- name: Install Poetry
env:
POETRY_VERSION: 2.4.3
run: |
curl -sSL https://install.python-poetry.org | python - -y &&\
poetry config virtualenvs.create false
run: pipx install "poetry==${POETRY_VERSION}"
- uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
cache: poetry
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
# if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
poetry install
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
# flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
run: poetry install
- name: Test with pytest
run: |
pytest
run: poetry run pytest
36 changes: 0 additions & 36 deletions .github/workflows/pythonpackage.yml

This file was deleted.

15 changes: 15 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Installed by `poetry run pre-commit install` (see CONTRIBUTING.md).
# Uses the isort and black installed by Poetry, so the version always matches poetry.lock and CI.
repos:
- repo: local
hooks:
- id: isort
name: isort
entry: poetry run isort
language: system
types: [python]
- id: black
name: black
entry: poetry run black
language: system
types: [python]
30 changes: 8 additions & 22 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -1,39 +1,25 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
# https://docs.readthedocs.io/en/stable/config-file/v2.html
version: 2

# Set the version of Python and other tools you might need
build:
os: ubuntu-22.04
os: ubuntu-24.04
tools:
python: "3.11"
python: "3.13"

# Build documentation in the docs/ directory with Sphinx
sphinx:
builder: html
configuration: docs/source/conf.py

formats:
- epub
- pdf

# We recommend specifying your dependencies to enable reproducible builds:
# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
# autodoc imports bindsnet, so the package and its dependencies must be installed.
# docs/requirements.txt installs the CPU build of torch first (much smaller than the
# CUDA build); installing the package then keeps that torch.
python:
install:
- requirements: docs/requirements.txt
- method: pip
path: docs/
# extra_requirements:
# - docs

# python:
# version: 3.8
# install:
# - method: pip
# path: .
# - requirements: docs/requirements.txt
# system_packages: False
path: .
17 changes: 0 additions & 17 deletions .vscode/launch.json

This file was deleted.

36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,42 @@ see the [GitHub releases / tags](https://github.com/BindsNET/bindsnet/releases).

## [Unreleased]

### Fixed
- API reference on Read the Docs was empty: the build never installed `bindsnet`, so
every `automodule` failed to import (`No module named 'matplotlib'`), and
`docs/pyproject.toml` downgraded Sphinx to 7.2.6. `.readthedocs.yaml` now installs a
CPU build of torch and the package (Python 3.13, Ubuntu 24.04);
`docs/pyproject.toml` removed.
- The docs build has no warnings (was 48 on Read the Docs, 53 with the package
installed): docstring markup fixed in `topology.py`, `topology_features.py`,
`monitors.py`, `learning.py`, `nodes.py`, `encoders.py`, `plotting.py`,
`conversion.py`, `davis.py`, `preprocess.py`, `cue_reward.py`, `dot_simulator.py`;
broken links in `index.rst` and the guide; `conf.py` takes the version from the
installed package. Docstring text only; no code changed.
- API reference now includes `learning.MCC_learning`, `network.topology_features`,
`environment.cue_reward`, `environment.dot_simulator` and
`analysis.dotTrace_plotter`, which were missing.

### Changed
- CI: one test workflow (`python-app.yml`: job `build` on Python 3.13 plus a 3.11/3.12
matrix, Poetry 2.4.3 with dependency caching, superseded runs cancelled);
`pythonpackage.yml` removed (it ran on every push to every branch and its
`black .` step reformatted instead of checking). `black.yml` checks with the black
version from `poetry.lock` instead of the floating `psf/black@stable`.
- Dependabot also updates the Dockerfile base image.
- Imports sorted with isort (settings already in `pyproject.toml`, never applied; 20
files, import order only). `black.yml` and the pre-commit hook now also check isort.
- Removed from git: 59 TensorBoard event files under `logs/` (test output; `logs/*`
was already in `.gitignore`), `.vscode/launch.json` (a local interpreter path) and
`docs/Makefile.old`, `docs/make.bat.old`.
- Added `.pre-commit-config.yaml` (black from Poetry); `CONTRIBUTING.md` already told
contributors to install pre-commit, but there was no configuration.
- `[tool.black] target-version` is `py311`-`py313` (was `py38`); no file changes.
- README: dead link to Markram et al. (1997) replaced with its DOI; RL example named
correctly (Breakout, not Space Invaders); OpenAI gym text replaced (Gymnasium and
ale-py install with BindsNET); benchmark marked as from the 2018 paper; PyPI badge
refreshes hourly.

## [0.3.4 (PyPI)] - 2026-09-16

First PyPI upload since 0.2.7. It is built from the `master` branch on this date, not
Expand Down
20 changes: 9 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<p align="center"><img width="25%" src="https://raw.githubusercontent.com/BindsNET/bindsnet/master/docs/logo.png"/></p>

A Python package used for simulating spiking neural networks (SNNs) on CPUs or GPUs using [PyTorch](http://pytorch.org/) `Tensor` functionality.
A Python package used for simulating spiking neural networks (SNNs) on CPUs or GPUs using [PyTorch](https://pytorch.org/) `Tensor` functionality.

BindsNET is a spiking neural network simulation library geared towards the development of biologically inspired algorithms for machine learning.

Expand All @@ -9,7 +9,7 @@ This package is used as part of ongoing research on applying SNNs, machine learn

Check out the [BindsNET examples](https://github.com/BindsNET/bindsnet/tree/master/examples) for a collection of experiments, functions for the analysis of results, plots of experiment outcomes, and more. Documentation for the package can be found [here](https://bindsnet-docs.readthedocs.io).

[![PyPI](https://img.shields.io/pypi/v/bindsnet.svg)](https://pypi.org/project/bindsnet/)
[![PyPI](https://img.shields.io/pypi/v/bindsnet.svg?cacheSeconds=3600)](https://pypi.org/project/bindsnet/)
[![Build Status](https://github.com/BindsNET/bindsnet/actions/workflows/python-app.yml/badge.svg?branch=master)](https://github.com/BindsNET/bindsnet/actions/workflows/python-app.yml)
[![CodeQL](https://github.com/BindsNET/bindsnet/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/BindsNET/bindsnet/actions/workflows/github-code-scanning/codeql)
[![Documentation Status](https://readthedocs.org/projects/bindsnet-docs/badge/?version=latest)](https://bindsnet-docs.readthedocs.io/?badge=latest)
Expand Down Expand Up @@ -57,7 +57,7 @@ Or, to install in editable mode (allows modification of package without re-insta
pip install -e .
```

To install the packages necessary to interface with the [OpenAI gym RL environments library](https://github.com/openai/gym), follow their instructions for installing the packages needed to run the RL environments simulator (on Linux / MacOS).
The reinforcement-learning environments use [Gymnasium](https://gymnasium.farama.org/) with the Arcade Learning Environment ([ale-py](https://github.com/Farama-Foundation/Arcade-Learning-Environment)); both are installed with BindsNET.

### Using Docker
The `Dockerfile` installs BindsNET with the dependency versions pinned in `poetry.lock`.
Expand Down Expand Up @@ -104,8 +104,6 @@ Issue the following to run the tests:
python -m pytest test/
```

Some tests will fail if Open AI `gym` is not installed on your machine.

## Datasets

BindsNET ships no third-party datasets; its loaders fetch them from upstream sources.
Expand All @@ -122,17 +120,17 @@ Hazan et al. 2018 scaling benchmark).

## Background

The simulation of biologically plausible spiking neuron dynamics can be challenging. It is typically done by solving ordinary differential equations (ODEs) which describe said dynamics. PyTorch does not explicitly support the solution of differential equations (as opposed to [`brian2`](https://github.com/brian-team/brian2), for example), but we can convert the ODEs defining the dynamics into difference equations and solve them at regular, short intervals (a `dt` on the order of 1 millisecond) as an approximation. Of course, under the hood, packages like `brian2` are doing the same thing. Doing this in [`PyTorch`](http://pytorch.org/) is exciting for a few reasons:
The simulation of biologically plausible spiking neuron dynamics can be challenging. It is typically done by solving ordinary differential equations (ODEs) which describe said dynamics. PyTorch does not explicitly support the solution of differential equations (as opposed to [`brian2`](https://github.com/brian-team/brian2), for example), but we can convert the ODEs defining the dynamics into difference equations and solve them at regular, short intervals (a `dt` on the order of 1 millisecond) as an approximation. Of course, under the hood, packages like `brian2` are doing the same thing. Doing this in [`PyTorch`](https://pytorch.org/) is exciting for a few reasons:

1. We can use the powerful and flexible [`torch.Tensor`](http://pytorch.org/) object, a wrapper around the [`numpy.ndarray`](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.ndarray.html) which can be transferred to and from GPU devices.
1. We can use the powerful and flexible [`torch.Tensor`](https://pytorch.org/docs/stable/tensors.html) object, an array similar to the [`numpy.ndarray`](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html) that can be moved to and from GPU devices.

2. We can avoid "reinventing the wheel" by repurposing functions from the [`torch.nn.functional`](http://pytorch.org/docs/master/nn.html#torch-nn-functional) PyTorch submodule in our SNN architectures; e.g., convolution or pooling functions.
2. We can avoid "reinventing the wheel" by repurposing functions from the [`torch.nn.functional`](https://pytorch.org/docs/stable/nn.functional.html) PyTorch submodule in our SNN architectures; e.g., convolution or pooling functions.

The concept that the neuron spike ordering and their relative timing encode information is a central theme in neuroscience. [Markram et al. (1997)](http://www.caam.rice.edu/~caam415/lec_gab/g4/markram_etal98.pdf) proposed that synapses between neurons should strengthen or degrade based on this relative timing, and prior to that, [Donald Hebb](https://en.wikipedia.org/wiki/Donald_O._Hebb) proposed the theory of Hebbian learning, often simply stated as "Neurons that fire together, wire together." Markram et al.'s extension of the Hebbian theory is known as spike-timing-dependent plasticity (STDP).
The concept that the neuron spike ordering and their relative timing encode information is a central theme in neuroscience. [Markram et al. (1997)](https://doi.org/10.1126/science.275.5297.213) proposed that synapses between neurons should strengthen or degrade based on this relative timing, and prior to that, [Donald Hebb](https://en.wikipedia.org/wiki/Donald_O._Hebb) proposed the theory of Hebbian learning, often simply stated as "Neurons that fire together, wire together." Markram et al.'s extension of the Hebbian theory is known as spike-timing-dependent plasticity (STDP).

We are interested in applying SNNs to ML and RL problems. We use STDP to modify weights of synapses connecting pairs or populations of neurons in SNNs. In the context of ML, we want to learn a setting of synapse weights which will generate data-dependent spiking activity in SNNs. This activity will allow us to subsequently perform some ML task of interest; e.g., discriminating or clustering input data. In the context of RL, we may think of the spiking neural network as an RL agent, whose spiking activity may be converted into actions in an environment's action space.

We have provided some simple starter scripts for doing unsupervised learning (learning a fully-connected or convolutional representation via STDP), supervised learning (clamping output neurons to desired spiking behavior depending on data labels), and reinforcement learning (converting observations from the Atari game Space Invaders to input to an SNN, and converting network activity back to actions in the game).
We have provided some simple starter scripts for doing unsupervised learning (learning a fully-connected or convolutional representation via STDP), supervised learning (clamping output neurons to desired spiking behavior depending on data labels), and reinforcement learning (converting observations from the Atari game Breakout to input to an SNN, and converting network activity back to actions in the game; see `examples/breakout`).

## Benchmarking
We simulated a network with a population of n Poisson input neurons with firing rates (in Hertz) drawn randomly from U(0, 100), connected all-to-all with a equally-sized population of leaky integrate-and-fire (LIF) neurons, with connection weights sampled from N(0,1). We varied n systematically from 250 to 10,000 in steps of 250, and ran each simulation with every library for 1,000ms with a time resolution dt = 1.0. We tested BindsNET (with CPU and GPU computation), BRIAN2, PyNEST (the Python interface to the NEST SLI interface that runs the C++NEST core simulator), ANNarchy (with CPU and GPU computation), and BRIAN2genn (the BRIAN2 front-end to the GeNN simulator).
Expand All @@ -143,7 +141,7 @@ Several packages, including BRIAN and PyNEST, allow the setting of certain globa
<img src="https://raw.githubusercontent.com/BindsNET/bindsnet/master/docs/BindsNET%20benchmark.png" alt="BindsNET%20Benchmark" width="503" height="403">
</p>

All simulations run on Ubuntu 16.04 LTS with Intel(R) Xeon(R) CPU E5-2687W v3 @ 3.10GHz, 128Gb RAM @ 2133MHz, and two GeForce GTX TITAN X (GM200) GPUs. Python 3.6 is used in all cases. Clock time was recorded for each simulation run.
These results are from the 2018 BindsNET paper. All simulations run on Ubuntu 16.04 LTS with Intel(R) Xeon(R) CPU E5-2687W v3 @ 3.10GHz, 128Gb RAM @ 2133MHz, and two GeForce GTX TITAN X (GM200) GPUs. Python 3.6 is used in all cases. Clock time was recorded for each simulation run.

## Citation

Expand Down
Loading