max-div
Configurable solver for Maximum Diversity Problems with optional fairness constraints:
given n items — vectors or precomputed distances — select the k most diverse, optionally
subject to per-group minimum/maximum quotas.
max-div is an anytime heuristic: it returns a good selection quickly and keeps improving it for as long as you allow (wall-clock time or iteration count). Two things set it apart among freely available tools: it is the only dedicated diversity solver with native support for overlapping fairness constraints, and the only one offering a geometric-mean separation objective — one of four diversity metrics it provides (minimum, mean, and geometric-mean separation, plus mean pairwise distance).
It fills the gap between exact MIP/CP solvers, which prove optimal answers but do not scale, and single-shot pickers, which are fast but at best have very limited support for constraints. The benchmarks show where it leads and where it does not.
Installation
Python 3.11+; free-threaded builds (3.14t) are supported and CI-tested (see the installation notes for the numba version they require).
Quick start
import numpy as np
from max_div import MaxDivProblem, MaxDivSolverBuilder, seconds
rng = np.random.default_rng(42)
vectors = rng.random((200, 5)) # 200 points in 5 dimensions
# select the 20 most diverse, improving for up to 5 seconds
problem = MaxDivProblem.new(vectors, k=20)
solution = MaxDivSolverBuilder(problem).with_preset(seconds(5)).build().solve()
print(solution.i_selected) # indices of the selected items
With fairness constraints
Require a minimum and/or maximum number of selected items from given subsets — useful for fair representation across groups. Groups may overlap, and infeasible constraints degrade gracefully to the least-infeasible selection rather than failing.
from max_div import Constraint
# require between 8 and 12 of the selected items from each half of the data
constraints = [
Constraint(int_set=set(range(0, 100)), min_count=8, max_count=12),
Constraint(int_set=set(range(100, 200)), min_count=8, max_count=12),
]
problem = MaxDivProblem.new(vectors, k=20, constraints=constraints)
Documentation
Full documentation lives at max-div.readthedocs.io, including:
- Getting started — installation, distance and diversity metrics, solver presets
- Comparison with other tools — how max-div relates to exact solvers, greedy pickers, and samplers
- Benchmarks — the measured comparison against third-party tools
License
Licensed under the Apache License 2.0.