Metadata-Version: 2.4
Name: snn_opt
Version: 0.1.0
Summary: A spiking neural network solver for constrained convex optimization (QP/LP).
Author-email: Ameer Hamza Khan <ahkhan@tzc.edu.cn>
License: Apache-2.0
Project-URL: Homepage, https://snn.ahkhan.me
Project-URL: Repository, https://github.com/ahkhan03/SNN_opt
Project-URL: Documentation, https://snn.ahkhan.me/docs
Project-URL: Issues, https://github.com/ahkhan03/SNN_opt/issues
Project-URL: Changelog, https://github.com/ahkhan03/SNN_opt/blob/main/CHANGELOG.md
Keywords: spiking-neural-networks,convex-optimization,quadratic-programming,neuromorphic-computing,projected-gradient
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.20
Requires-Dist: scipy>=1.7
Provides-Extra: examples
Requires-Dist: matplotlib>=3.5; extra == "examples"
Provides-Extra: benchmarks
Requires-Dist: matplotlib>=3.5; extra == "benchmarks"
Requires-Dist: cvxpy>=1.4; extra == "benchmarks"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"
Requires-Dist: matplotlib>=3.5; extra == "dev"
Requires-Dist: cvxpy>=1.4; extra == "dev"
Dynamic: license-file

# snn_opt

**A spiking neural network solver for constrained convex optimization.**

[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
[![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/downloads/)
[![Version](https://img.shields.io/badge/version-0.1.0-informational.svg)](CHANGELOG.md)
[![Cite](https://img.shields.io/badge/cite-CITATION.cff-orange.svg)](CITATION.cff)
[![Docs](https://img.shields.io/badge/docs-snn.ahkhan.me-success.svg)](https://snn.ahkhan.me)

---

## Abstract

`snn_opt` is a Python implementation of the **spiking neural network (SNN) → convex optimization** equivalence, developed as part of an ongoing research program on neuromorphic computation for classical machine-learning problems. It solves quadratic and linear programs of the form

$$
\min_{x \in \mathbb{R}^n}\ \tfrac{1}{2}\, x^\top A x + b^\top x
\quad\text{subject to}\quad C x + d \le 0,
$$

by alternating gradient descent — playing the role of leaky-integrate membrane drift — with discrete projection events that clamp the trajectory to the constraint boundary, the optimization analogue of an integrate-and-fire **spike**. The construction follows Mancoo, Boerlin and Machens ([NeurIPS 2020](https://papers.nips.cc/paper/2020/hash/64714a86909d401f8feb83e8c2d94b23-Abstract.html)) and is the canonical solver underlying the **SNN-X** publication series (PCA, Ridge, TDSVM, Norm, SVM, CF, KRR, Procrustes — see [Applications](#applications)).

This repository is intended both as a **research artifact** — every published SNN-X paper can be reproduced from the code here — and as a **teaching resource** for students entering the area: it ships with annotated examples, a self-contained mathematical writeup, and a benchmark suite that visualizes convergence and projection dynamics.

## The problem

Given a positive semi-definite Hessian $A \in \mathbb{R}^{n\times n}$, a linear cost $b \in \mathbb{R}^n$, and $m$ linear inequality constraints stacked into $C \in \mathbb{R}^{m \times n}$ and $d \in \mathbb{R}^m$, we seek

$$
x^\star \;=\; \arg\min_{x}\ \tfrac{1}{2}\, x^\top A x + b^\top x \quad\text{s.t.}\quad c_i^\top x + d_i \le 0,\ i = 1,\dots,m.
$$

The class subsumes box-constrained QPs (set $C = [I; -I]$), linear programs ($A = 0$), kernel-ridge subproblems, support-vector machine duals, projected-gradient flows on polytopes, and the bulk of the inner solves that arise in receding-horizon control.

## The spiking idea, in one picture

The continuous-time dynamics

$$
\dot x \;=\; -\nabla f(x) \;-\; C^\top s(t)
$$

models a population of $n$ leaky integrators driven by the gradient $\nabla f(x) = Ax + b$, with a corrective spike train $s(t)$ that fires whenever an inequality $c_i^\top x + d_i$ would otherwise become positive. Each spike applies a *minimal* projection that re-enters the feasible set; spike inter-arrival times encode constraint *traffic*. Discretized with forward Euler and an adaptive step that reaches the boundary exactly, this becomes a fast projected-gradient solver with diagnostics that double as a neural raster plot.

See [`docs/theory.md`](docs/theory.md) for the full derivation, including the eigenvalue-based step-size choice that eliminates `k0` as a hyperparameter and the box-clipping shortcut for problems like SVM.

## Convergence and projection dynamics

Three diagnostic figures, regenerated from [`benchmarks/`](benchmarks/), give a quick visual sense of what the solver actually does:

| | |
|---|---|
| **Convergence** on a random 50-D QP with 30 inequalities. The objective gap drops geometrically over a few thousand iterations; the iterate stability `‖x_{t+1}−x_t‖` mirrors it; constraint violation stays at machine-precision floor throughout. | ![convergence](figures/01_convergence.png) |
| **Projection-spike raster** on a 4-D box-constrained problem whose unconstrained optimum lies *outside* the box. Each row is one inequality, each marker a spike (sized by displacement); only the four "active" faces of the box fire. The bottom panel is the corresponding objective gap. This is the literal sense in which the solver is *spiking*. | ![spike raster](figures/02_spike_raster.png) |
| **Warm-start speedup** on a sequence of 30 drifting QPs (a stylized MPC workload). Cold-started solves take ~260 iterations each; warm-started solves drop to ~140 from the second problem onward — an essentially-free 1.8× speedup, the property that makes this dynamic well-suited to receding-horizon problems. | ![warm start](figures/03_warm_start.png) |

Reproduce these from a checkout with `python benchmarks/run_all.py`.

### A closer look: trajectory and raw-vs-optimized modes

Two figures generated by the example scripts give a more concrete sense of what the dynamics look like in 2-D, where everything is easy to visualize:

![2-D trajectory and projection spikes](examples/example1_basic_2d.png)

*State evolution and 2-D trajectory for `examples/example1_basic_2d.py` — a constrained QP whose unconstrained minimum lies outside the feasible polytope. Left: per-component value over time, with orange spike markers at projection events. Right: the trajectory in state space superimposed on objective contours; the trajectory glides down the gradient, hits the active facet, and slides along it to the constrained optimum.*

![raw vs optimized solver mode](examples/raw_vs_optimized.png)

*Output of `examples/example_raw_mode.py`. Left two panels: the trajectory under "raw" (no auto step size, no adaptive projection) and "optimized" defaults — both reach the optimum, but the optimized run does so in 201 iterations with a single projection event versus 300 / 5. Right: convergence on a log-objective scale; the optimized run gains roughly 30 orders of magnitude per 100 iterations once it leaves the boundary.*

## Installation

`snn_opt` requires Python 3.9+, NumPy, and SciPy. The fastest path is PyPI:

```bash
pip install snn-opt                # core, prebuilt wheel (no compiler needed)
pip install "snn-opt[examples]"    # also installs matplotlib for examples
pip install "snn-opt[dev]"         # examples + cvxpy + pytest + ruff
```

> The PyPI distribution name is `snn-opt` (hyphenated, lowercase, per PEP 503); the Python import name is `snn_opt`. So you `pip install snn-opt` and then `import snn_opt`.

For an editable install from a checkout (development workflow):

```bash
git clone https://github.com/ahkhan03/SNN_opt.git
cd SNN_opt
pip install -e .                   # core
pip install -e ".[examples]"       # also installs matplotlib for examples
pip install -e ".[dev]"            # examples + cvxpy + pytest + ruff
```

For a specific commit (reproducibility for papers/collaborators):

```bash
pip install "git+https://github.com/ahkhan03/SNN_opt.git@<commit-sha>"
```

The package can also be run **without** installation — every example and test sits next to a small `sys.path` bootstrap that points at `src/`. Smoke test:

```bash
python tests/test_installation.py
```

### Compiled C++ backend

The PyPI wheels ship a precompiled C++ kernel (`snn_opt._kernel`) that accelerates the inner adaptive-projection loop by roughly an order of magnitude over the pure-Python path. Opt in via the `backend` keyword:

```python
result = solve_qp(A, b, C, d, x0, backend='c')   # compiled kernel
result = solve_qp(A, b, C, d, x0, backend='python')  # reference (default)
```

Both backends are kept in lockstep by the parity test suite (`tests/test_c_backend_parity.py`). The C kernel supports dense problems with `projection_method='adaptive'`; sparse and non-adaptive paths transparently use Python. The same kernel source is HLS-compatible and is the basis for the planned FPGA deployment track. When the precompiled kernel is unavailable on your platform (rare), `backend='c'` raises a clear error and the Python backend continues to work.

## Quick start

```python
import numpy as np
from snn_opt import solve_qp

# Minimize ||x||^2 subject to  x_1 + 2 x_2 <= 1  (and that's it).
A  = np.eye(2)
b  = np.zeros(2)
C  = np.array([[1.0, 2.0]])
d  = np.array([-1.0])
x0 = np.array([1.0, 1.0])

result = solve_qp(A, b, C, d, x0, max_iterations=1000)

print(result.summary())             # converged?  iterations?  spikes?
print("x* =", result.final_x)
print("f* =", result.final_objective)
```

For repeated solves (warm-started receding-horizon problems), construct an `SNNSolver` once and call `.solve(x0)` per problem instance — see [`examples/example4_warm_start.py`](examples/example4_warm_start.py).

## Examples

All scripts live under [`examples/`](examples/) and are runnable as plain `python examples/example_name.py`.

| # | Script | Problem | Highlights |
|---|---|---|---|
| 1 | [`example1_simple_2d.py`](examples/example1_simple_2d.py) | 2D quadratic with two linear cuts | Smallest possible runnable demo |
| 1b | [`example1_basic_2d.py`](examples/example1_basic_2d.py) | Same problem, with trajectory plot | See `examples/example1_basic_2d.png` |
| 1c | [`example1_advanced_2d.py`](examples/example1_advanced_2d.py) | Shifted feasible region, infeasible start | Spike raster + violation plot |
| 2 | [`example2_3d_polytope.py`](examples/example2_3d_polytope.py) | 3D QP with 4 hyperplanes | Multiple active constraints, vertex solution |
| 3 | [`example3_linear_program.py`](examples/example3_linear_program.py) | Box-constrained LP ($A=0$) | LP via the same machinery |
| 4 | [`example4_warm_start.py`](examples/example4_warm_start.py) | Sequence of related QPs | Receding-horizon / MPC pattern; spikes drop $30 \to 0$ |
| 5 | [`example5_infeasible_recovery.py`](examples/example5_infeasible_recovery.py) | Infeasible initializations | Automatic projection to feasibility |
| 6 | [`example6_equality_constraint.py`](examples/example6_equality_constraint.py) | Equality via a sandwiched band | $x_1 = a$ as a tight $\pm \varepsilon$ inequality pair |
| 7 | [`example7_svm_dual.py`](examples/example7_svm_dual.py) | SVM dual with kernel | Box clipping + auto step size on a real ML task |
| — | [`example_raw_mode.py`](examples/example_raw_mode.py) | Bypass auto-config | Compares raw vs. optimized solver settings |

Run them all in sequence:

```bash
python examples/run_all_examples.py
```

## Documentation

- [`docs/theory.md`](docs/theory.md) — derivation of the SNN/convex-optimization equivalence, step-size analysis, projection geometry, convergence criteria.
- [`docs/applications.md`](docs/applications.md) — one-page summary of each SNN-X paper with links to PDFs.
- [`docs/api.md`](docs/api.md) — hand-curated API reference.
- [https://snn.ahkhan.me](https://snn.ahkhan.me) — companion site, designed for a broader audience (students, curious researchers).

## Applications

The framework is currently demonstrated in:

- **Khan, Mohammed & Li (2025)** — *Portfolio Optimization: A Neurodynamic
  Approach Based on Spiking Neural Networks*, **Biomimetics**, 10(12):808.
  [doi:10.3390/biomimetics10120808](https://doi.org/10.3390/biomimetics10120808).
  Portfolio selection cast as a constrained QP and solved by the spiking
  dynamics implemented here.

Additional applications are in preparation. As they reach publication
they will be added to [`docs/applications.md`](docs/applications.md).

## Citing this work

If `snn_opt` plays a role in your research or teaching, please cite both the software and the framework paper:

```bibtex
@software{khan2026snnopt,
  author  = {Khan, Ameer Hamza and Li, Shuai},
  title   = {snn\_opt: A Spiking Neural Network Solver for Constrained Convex Optimization},
  year    = {2026},
  version = {0.1.0},
  url     = {https://github.com/ahkhan03/SNN_opt},
  license = {Apache-2.0},
}

@inproceedings{mancoo2020understanding,
  author    = {Mancoo, Allan and Boerlin, Martin and Machens, Christian K.},
  title     = {Understanding Spiking Networks Through Convex Optimization},
  booktitle = {Advances in Neural Information Processing Systems (NeurIPS)},
  year      = {2020},
}
```

The full per-paper bibliography of the SNN-X series is maintained at [`docs/applications.md`](docs/applications.md).

## License

Apache-2.0 — see [`LICENSE`](LICENSE). Permissive, with an explicit patent grant; suitable for both academic and commercial reuse.

## Acknowledgments

Developed at the **School of Artificial Intelligence, Taizhou University**.

This codebase implements the SNN-QP research program led by **Prof. Shuai Li** (IEEE Fellow; Faculty of Information Technology and Electrical Engineering, University of Oulu, Finland), who originated the line of work and co-authors the application papers in the SNN-X series. The mathematical framework follows Mancoo, Boerlin and Machens (NeurIPS 2020) and the broader projection-neural-network lineage (Hopfield–Tank, Kennedy–Chua, Xia–Wang, Liu–Wang). Pull requests, bug reports, and citations of the SNN-X papers in your own work are all warmly welcomed.
