GPU-native parallel optimizer for multimodal black-box functions via convergence-anticonvergence oscillation
Project description
ChiSao
Convergence-Halt-Invert-Stick-And-Oscillate — a GPU-native population optimizer for finding all modes of a multimodal black-box function.
ChiSao runs an entire sample batch simultaneously and exploits a deliberate convergence/anti-convergence oscillation cycle to escape local traps while freezing confirmed modes. On a GPU, an entire population advances in the same wall-clock time as a single sample, so cataloguing every mode of a hard landscape costs roughly what one gradient step would cost on a CPU.
The name is from Wing Chun Chí Sǎo ("sticky hands"): sensitivity drills that train simultaneous contact maintenance and redirection — the explore-and-freeze asymmetry at the heart of the algorithm.
ChiSao began as the mode-discovery engine of the SunBURST Bayesian-evidence pipeline and is published here as a standalone optimizer.
Install
pip install chisao
GPU acceleration is optional. Install the CuPy wheel matching your CUDA driver
(check nvidia-smi):
pip install "chisao[cuda13]" # CUDA 13.x driver
pip install "chisao[cuda12]" # CUDA 12.x driver
pip install "chisao[cuda11]" # CUDA 11.x driver
Without CuPy, ChiSao runs on NumPy (CPU) automatically. If CuPy is installed but
its CUDA libraries are broken or mismatched, ChiSao detects this at import and
falls back to CPU instead of crashing (check chisao.GPU_OK, or force CPU with
the CHISAO_FORCE_CPU=1 environment variable).
Quick start
import numpy as np
from chisao import optimize
# Objective must return LOG-likelihood, batched: f(X[n, d]) -> [n].
# (Maximization. Negate a cost function to maximize it.)
def neg_rastrigin(X):
A = 10.0
d = X.shape[1]
return -(A * d + np.sum(X**2 - A * np.cos(2 * np.pi * X), axis=1))
bounds = [(-5.12, 5.12)] * 8
peaks, logL = optimize(neg_rastrigin, bounds, seeder="carry_tiger", seed=0)
print(peaks.shape, "modes found; best logL =", logL.max())
Seeding matters
ChiSao optimizes whatever initial population you hand it. Where that population starts is a first-class algorithmic choice, not a detail. On landscapes with large gradient-free regions (Ackley) or product-coupled minima (Griewank), a uniformly random population never reaches the global basin, while a population seeded by structured rays cast through the domain geometry does.
Two seeders ship in chisao.seeding:
| Seeder | What it does |
|---|---|
random |
Uniform i.i.d. over the box. The baseline. |
carry_tiger |
Structured rays between vertices, vertex-to-edge, wall-to-wall, and a QR-orthonormal "sunburst" from the center — the seeding the paper shows is essential on flat/coupled landscapes. |
from chisao import optimize, carry_tiger_seed, random_seed, sticky_hands
# High-level: seed + run in one call
peaks, logL = optimize(f, bounds, seeder="carry_tiger")
# Or build the population yourself and call the core optimizer directly
x0 = carry_tiger_seed(f, bounds, n_samples_per_ray=50, seed=0)
result = sticky_hands(f, x0, bounds=np.asarray(bounds, float), n_oscillations=3)
peaks, logL, widths = result["peaks"], result["L_peaks"], result["widths"]
How it works
Each oscillation cycle runs six phases in fixed order:
- Convergence — the whole population takes batched L-BFGS steps toward local maxima.
- Stick detection — samples at true peaks (gradient-norm + quality gate) are frozen.
- Deduplication — coincident peaks are merged in the L∞ metric (the load-bearing step).
- Reseeding — Repulse Monkey (many free samples) or Golden Rooster (near exhaustion) refill the population.
- Hands Like Clouds — unfrozen samples ascend a Gaussian-smoothed gradient to see global structure through local ripples.
- Anti-convergence — momentum-based descent disperses unfrozen samples across valleys into new basins.
Frozen samples sit out the exploration phases but keep refining their peak. The last oscillation skips phases 4–6 so the final output is clean.
API
| Object | Purpose |
|---|---|
optimize(func, bounds, seeder=...) |
Seed a population and run ChiSao; returns (peaks, L_peaks). |
sticky_hands(func, x0, ...) |
The core oscillation optimizer over a given population. |
carry_tiger_seed, random_seed, carry_tiger_rays |
Population seeders. |
lbfgs_batch, gradient_ascent_batch, optimize_batch |
Batched local optimizers. |
deduplicate_peaks_L_infinity, estimate_peak_width |
Mode post-processing. |
SingleWhip, randcoord_line_search_batch |
GPU batch toolkit (line search, scales, distances). |
get_gpu_info, get_array_module, GPU_OK |
Backend introspection / NumPy-or-CuPy selection. |
func must return log-likelihood and accept a batched input X[n, d].
On a GPU, results are returned as CuPy arrays (call .get() for host copies);
on CPU they are NumPy arrays.
Reproducing the paper
benchmarks/sfu_benchmark.py runs the 42-function Simon Fraser University suite
for both seeders across dimension. See benchmarks/README.md for the exact
settings used in the paper.
Citation
@article{wolfson_chisao,
title = {ChiSao: A GPU-Native Parallel Optimizer for Multimodal Black-Box
Functions via Convergence-Anticonvergence Oscillation},
author = {Wolfson, Ira},
year = {2026}
}
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chisao-0.1.1.tar.gz.
File metadata
- Download URL: chisao-0.1.1.tar.gz
- Upload date:
- Size: 71.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f1b0d71ab3456113b2fe53858e304480299ab3d7f239aab099255992a6d3351
|
|
| MD5 |
578dbaa3539c793e026d62dc854bd8cc
|
|
| BLAKE2b-256 |
30086a5346c0bc1d2ff7176bc02d0d1c97d1c7545ff6d3b3002ab2deccf8056f
|
File details
Details for the file chisao-0.1.1-py3-none-any.whl.
File metadata
- Download URL: chisao-0.1.1-py3-none-any.whl
- Upload date:
- Size: 60.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5694e8750c04cd30a9dfb817afb9154f9d2e58eb1e4ef267815622e3cb1e7bf4
|
|
| MD5 |
f5852abce285fa82578b8c642549027d
|
|
| BLAKE2b-256 |
f4044375c062c8fb939852fb4c10e37b177b923b5206005cb9e59382cdba8fb7
|