Gradient-free multi-objective alignment via Sperner's Lemma and implicit Freudenthal triangulation.
Project description
Sperner
Find the optimal balance between competing objectives — without gradients, without grid search, with a mathematical guarantee.
What does Sperner do?
You have an LLM (or any system) with N competing objectives — Safety vs. Helpfulness vs. Creativity, or Precision vs. Recall vs. Latency. You need to find the weight mix where everything is "good enough" simultaneously.
Sperner solves this in O(N) evaluations using a topological fixed-point algorithm (Sperner's Lemma), instead of the O(X^N) brute-force grid search.
# Find the optimal balance between 3 objectives in ~50 evaluations
from sperner import solve_equilibrium
weights = solve_equilibrium(
n_objs=3,
oracle=lambda w: my_benchmark(w), # returns index of weakest objective
)
# weights ≈ [0.35, 0.40, 0.25] — the Nash equilibrium
When to use Sperner
| Use case | Example |
|---|---|
| LLM alignment | Balance safety, helpfulness, and creativity |
| Model merging | Find optimal LoRA adapter mix weights |
| MoE routing | Allocate experts without softmax collapse |
| Benchmark tuning | Hit multiple non-differentiable metrics at once |
| Any multi-objective problem | Where you can answer "which objective is weakest?" |
The only requirement: you need an oracle that, given a weight vector, tells you which objective is currently the most underserved. That's it — no gradients, no loss surfaces, no hyperparameter sweeps.
How it works (30-second version)
- Sperner places your N objectives on an N-simplex (triangle for 3, tetrahedron for 4, etc.)
- It subdivides the simplex into a fine grid and labels each point by asking your oracle: "at these weights, which objective is weakest?"
- It performs a Sperner walk — a combinatorial path through the grid that is mathematically guaranteed to find a cell where all labels meet (a "panchromatic simplex")
- The centroid of that cell is your equilibrium — the weight mix where no single objective dominates
This works because of Sperner's Lemma (1928): any valid labeling of a triangulated simplex must contain at least one fully-labeled cell. Sperner exploits this to find it in linear time.
Installation
pip install .
# With LoRA/PEFT support
pip install ".[peft]"
# With Streamlit human-in-the-loop UI
pip install ".[ui]"
# Everything
pip install ".[all]"
Quick start
Automated (programmatic oracle)
import numpy as np
from sperner import NDimEquilibSolver
import torch
solver = NDimEquilibSolver(n_objs=4, subdivision=50)
def judge(weights_batch: torch.Tensor) -> torch.Tensor:
"""Return index of the weakest objective for each weight vector."""
labels = []
for w in weights_batch:
scores = run_my_benchmarks(w.numpy()) # your eval function
labels.append(int(np.argmin(scores)))
return torch.tensor(labels)
optimal = solver.solve(oracle_fn=judge)
print(f"Optimal weights: {optimal[0]}")
Human-in-the-loop (Streamlit UI)
For qualitative "vibe check" alignment — the solver proposes weights, your local LLM generates a response, and you click which objective needs more work:
streamlit run app.py
The UI supports 2–10 configurable objectives and works with any OpenAI-compatible API (LM Studio, Ollama, vLLM).
LoRA adapter merging
from sperner import SpernerTrainer
trainer = SpernerTrainer(
base_model=my_peft_model,
adapters=["safety-lora", "code-lora", "chat-lora"],
objectives=[safety_score, code_score, chat_score],
mock=False,
)
optimal_mix = trainer.train(grid_size=50)
MoE expert routing
from sperner import TopologicalMoERouter
router = TopologicalMoERouter(num_experts=8, latent_dim=4096)
weights = router.forward_route(hidden_states, precision=20)
# weights = [0.18, 0.12, 0.15, ...] — no routing collapse
Comparison
| Grid Search | Bayesian Opt | Sperner | |
|---|---|---|---|
| Oracle calls | O(X^N) exponential | O(N²) typical | O(N) linear |
| Needs gradients | No | No | No |
| Scales to 10+ objectives | No | Poorly | Yes |
| Convergence guarantee | Exhaustive only | Probabilistic | Mathematical |
| Works with discrete metrics | Yes | Awkward | Native |
Project structure
sperner/
ndim_solver.py # Core N-dimensional Sperner walk (PyTorch)
solver.py # Legacy 2D solver
adaptive_solver.py # Iterative zoom refinement
surrogate_solver.py # KNN active-learning wrapper (fewer oracle calls)
sperner_trainer.py # PEFT/LoRA adapter integration
moe_router.py # Topological MoE routing
agentic_judge.py # LLM-as-a-Judge orchestrator
human_ui.py # Streamlit UI for manual alignment
analytics.py # Frustration score & path analysis
plotting.py # Simplex heatmap visualization
Docs
Citation
@software{mesbah2026sperner,
author = {Mesbah, Oussama},
title = {Sperner: Gradient-Free Multi-Objective Alignment via Sperner's Lemma},
year = {2026},
url = {https://github.com/OussamaMesbah/sperner}
}
License
MIT
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 sperner-0.1.0.tar.gz.
File metadata
- Download URL: sperner-0.1.0.tar.gz
- Upload date:
- Size: 96.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e0d1e0fc4769b6727fa2878280f907abf93488533bc2e8490398a1743025348c
|
|
| MD5 |
d3dabfb92ce3ef35b900d0b3841c66c1
|
|
| BLAKE2b-256 |
7279d33ec9d5e6457d9905bc555ae7b95c083bda7b74e9d218b6aad3cfe08af6
|
Provenance
The following attestation bundles were made for sperner-0.1.0.tar.gz:
Publisher:
publish.yml on OussamaMesbah/sperner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sperner-0.1.0.tar.gz -
Subject digest:
e0d1e0fc4769b6727fa2878280f907abf93488533bc2e8490398a1743025348c - Sigstore transparency entry: 1042954434
- Sigstore integration time:
-
Permalink:
OussamaMesbah/sperner@5b1c9a6d9cfb23918753d5fc8b99e97e83ce7e22 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/OussamaMesbah
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5b1c9a6d9cfb23918753d5fc8b99e97e83ce7e22 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file sperner-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sperner-0.1.0-py3-none-any.whl
- Upload date:
- Size: 34.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
74eff2018e72b09aa21cd011c7feca4851a55940f202411369dfeb9d714ab5cf
|
|
| MD5 |
227aee543f3319beb7c2fad5b89c1e21
|
|
| BLAKE2b-256 |
b6f4e51450b1a58610fe91a63f5ed6a0fe87acd10a910e9189ec28f9cb993d81
|
Provenance
The following attestation bundles were made for sperner-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on OussamaMesbah/sperner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sperner-0.1.0-py3-none-any.whl -
Subject digest:
74eff2018e72b09aa21cd011c7feca4851a55940f202411369dfeb9d714ab5cf - Sigstore transparency entry: 1042954439
- Sigstore integration time:
-
Permalink:
OussamaMesbah/sperner@5b1c9a6d9cfb23918753d5fc8b99e97e83ce7e22 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/OussamaMesbah
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5b1c9a6d9cfb23918753d5fc8b99e97e83ce7e22 -
Trigger Event:
workflow_dispatch
-
Statement type: