Adaptive Mirror-Consensus Particle Swarm Optimization (AMC-PSO): a gradient-assisted swarm optimizer with entropy-regulated annealing and free feasibility on constrained domains.
Project description
amcpso — Adaptive Mirror-Consensus Particle Swarm Optimization
amcpso is a gradient-assisted particle swarm optimizer that evolves particles
in the dual space of a strongly convex mirror potential. This buys two
things classical PSO doesn't have:
- Feasibility by construction. With the entropic mirror, every iterate is
automatically a valid point on the probability simplex (
x_k >= 0,sum(x) == 1) — no clip-and-renormalize projection distorting the search. - Entropy-regulated annealing. A swarm-dispersion signal
r_t in [0, 1]closes a feedback loop that cools exploration (noise, consensus pull) automatically as the swarm converges, instead of using a fixed schedule.
It combines five forces per iteration — inertia, natural-gradient descent, mirrored cognitive/social attraction, graph-Laplacian consensus over a time-varying neighborhood topology, and annealed Gaussian noise.
Installation
pip install amcpso
Requires Python >= 3.8 and NumPy >= 1.20.
When to use it (and when not to)
Use amcpso when your problem is constrained, geometry-sensitive, and/or
multimodal:
- Simplex-constrained problems — recovering or optimizing over a
probability distribution, mixture weights, portfolio allocations, or any
compositional/proportion data (
h_type='entropic'). This is where the mirror machinery pays off most: feasibility is structural, not statistical, and the algorithm is significantly better than projection-based PSO in the reference benchmarks. - Rugged, multimodal landscapes in ordinary
R^d(h_type='euclidean'), such as the Rastrigin function. The entropy-regulated schedule and local (rather than global-best) topology help delay premature convergence to a poor local minimum, and it is competitive-to-better than classical constriction PSO in the reference benchmarks. - You have (or can cheaply compute, e.g. via autodiff or finite differences)
a gradient of the objective —
amcpsois gradient-assisted, not a purely black-box method.
Don't expect a win when:
- Your objective is smooth and unimodal (e.g. a plain quadratic bowl) — classical PSO's noiseless contraction is typically competitive or better here, consistent with the No-Free-Lunch theorem.
- You have no usable gradient and computing one is expensive or impossible — consider a derivative-free method instead.
Quick start
import numpy as np
from amcpso import amc_pso
def sphere(x):
return float(np.sum(x**2))
def sphere_grad(x):
return 2 * x
x_best, f_best = amc_pso(sphere, sphere_grad, d=5, seed=0)
print(x_best, f_best)
The function: amc_pso(...)
from amcpso import amc_pso
x_best, f_best = amc_pso(
f, grad_f, d,
N=50, T=500, h_type='euclidean', init_range=(-5, 5),
beta=0.7, eta0=0.05, c10=1.5, c20=1.5, lambda0=0.3,
T0=0.5, alpha=5.0, gamma=1.0, bandwidth=2.0, epsilon=1e-10,
kappa=1e-3, p=0.5, G_max=10.0, v_max=None,
natural='diag', naive=False, entropy_feedback=True,
return_history=False, seed=None,
)
Required arguments
| Argument | Type | Description |
|---|---|---|
f |
callable | Objective function f(x) -> float, x is shape (d,). The function being minimized. |
grad_f |
callable | Gradient grad_f(x) -> array of shape (d,). Required — amcpso is gradient-assisted. |
d |
int | Problem dimension. |
Key optional arguments
| Argument | Default | Description |
|---|---|---|
N |
50 |
Swarm size. |
T |
500 |
Number of iterations (optimization budget). |
h_type |
'euclidean' |
'euclidean' for unconstrained R^d; 'entropic' for the probability simplex (feasibility for free). |
init_range |
(-5, 5) |
Per-coordinate init range, used only for h_type='euclidean'. |
beta |
0.7 |
Inertia weight, in [0, 1). |
eta0, p |
0.05, 0.5 |
Step-size schedule eta_t = eta0 / (1 + t) ** p. |
c10, c20 |
1.5, 1.5 |
Initial cognitive / social gains (linearly annealed to 0). |
lambda0 |
0.3 |
Base consensus gain; effective gain scales with the dispersion ratio r_t. |
T0, alpha, gamma |
0.5, 5.0, 1.0 |
Exploration temperature schedule. |
bandwidth, kappa |
2.0, 1e-3 |
Gaussian-kernel neighborhood topology bandwidth and cutoff. |
G_max |
10.0 |
Gradient-norm clip (rescales, doesn't truncate). |
v_max |
None |
Optional dual-velocity norm clip for extra robustness. |
natural |
'diag' |
Natural-gradient preconditioner for the entropic mirror: 'diag' or 'fisher'. |
return_history |
False |
If True, also return a dict of per-iteration traces (best, r, T, lam, eta). |
seed |
None |
RNG seed for reproducibility. |
naive, entropy_feedback |
False, True |
Ablation flags — leave at defaults for actual optimization; see the docstring for details. |
Full parameter-by-parameter documentation is available in the function's
docstring: help(amc_pso).
Returns
x_best(numpy.ndarray, shape(d,)) — best position found.f_best(float) — objective value atx_best.history(dict, only ifreturn_history=True) — per-iteration traces.
Example: multimodal optimization (Rastrigin, R^d)
This is the best-use-case scenario for the Euclidean mirror: a rugged, multimodal landscape.
import numpy as np
from amcpso import amc_pso
from amcpso.benchmarks import rastrigin, rastrigin_grad
d = 10
x_best, f_best = amc_pso(
rastrigin, rastrigin_grad, d=d,
h_type='euclidean', init_range=(-5.12, 5.12),
N=50, T=500, seed=7,
)
print(f"best objective: {f_best:.4f}")
Example: constrained optimization on the probability simplex
This is the best use case for amcpso: recovering a probability vector
x* on the simplex from noisy linear measurements b = A @ x*, where every
iterate must satisfy x >= 0 and sum(x) == 1.
import numpy as np
from amcpso import amc_pso
rng = np.random.default_rng(12345)
d = 20
A = rng.standard_normal((40, d))
x_star = rng.dirichlet(np.ones(d)) # ground truth on the simplex
b = A @ x_star
def loss(x):
return float(np.sum((A @ x - b) ** 2))
def loss_grad(x):
return 2.0 * A.T @ (A @ x - b)
x_best, f_best = amc_pso(loss, loss_grad, d=d, h_type='entropic', seed=0)
print("sum(x_best) =", x_best.sum()) # 1.0, always -- feasible by construction
print("min(x_best) =", x_best.min()) # >= 0, always
print("loss =", f_best)
Unlike classical PSO with clip-and-renormalize projection, amc_pso with
h_type='entropic' never produces an infeasible iterate at any point during
the search — the softmax inverse mirror map guarantees it structurally.
Diagnosing convergence with return_history
x_best, f_best, hist = amc_pso(
rastrigin, rastrigin_grad, d=10,
h_type='euclidean', init_range=(-5.12, 5.12),
seed=7, return_history=True,
)
# hist['best']: best-so-far objective per iteration
# hist['r']: dispersion ratio r_t in [0, 1]
# hist['T']: temperature T_t
# hist['lam']: consensus gain lambda_t
# hist['eta']: step size eta_t
Algorithm summary
Each particle keeps a primal position x, a dual variable y = grad_h(x),
and a dual velocity v. Every iteration:
- Rebuilds a time-varying neighborhood topology from a thresholded Gaussian kernel on pairwise distances.
- Measures swarm dispersion
S_t(half log-determinant of the swarm covariance) and derives a dispersion ratior_t = min(1, exp((S_t - S_0) / d)), which drives the consensus gain and temperature schedules. - Updates the dual velocity as the sum of inertia, natural-gradient descent, cognitive attraction, social attraction, Laplacian consensus, and annealed noise.
- Maps back to the primal space with the inverse mirror map
(
x = grad_h_star(y)), which is the identity for the Euclidean mirror and a softmax for the entropic mirror.
See the function docstring (help(amc_pso)) and the accompanying manuscript
for the full derivation.
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 amcpso-1.0.0.tar.gz.
File metadata
- Download URL: amcpso-1.0.0.tar.gz
- Upload date:
- Size: 15.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
956514d502219ccb6ca91091b65d53c12f9f673a14822f98370209566bf5dead
|
|
| MD5 |
1171e0268c64839f86cd950128c58297
|
|
| BLAKE2b-256 |
bd285973b1d4b10fb6ebb972abb7e4d7f8429ba455d1a593374afe0db41fbe60
|
Provenance
The following attestation bundles were made for amcpso-1.0.0.tar.gz:
Publisher:
publish.yml on razibmustafiz/AMC-PSO
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
amcpso-1.0.0.tar.gz -
Subject digest:
956514d502219ccb6ca91091b65d53c12f9f673a14822f98370209566bf5dead - Sigstore transparency entry: 2118825507
- Sigstore integration time:
-
Permalink:
razibmustafiz/AMC-PSO@da1ba7bfd290b7760419cf30b41c0781ae33a496 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/razibmustafiz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@da1ba7bfd290b7760419cf30b41c0781ae33a496 -
Trigger Event:
release
-
Statement type:
File details
Details for the file amcpso-1.0.0-py3-none-any.whl.
File metadata
- Download URL: amcpso-1.0.0-py3-none-any.whl
- Upload date:
- Size: 12.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
21d267fa6bb65dd77da9cbee66fc4781488b9eb4f1ceae3a5c8a0a9b66f72eed
|
|
| MD5 |
2645650881ae5832af2ce769fe03f765
|
|
| BLAKE2b-256 |
5a4e96bbc52f10d307e5733e1a42d5a0e987e1cdf2d99881b94516880616b4bc
|
Provenance
The following attestation bundles were made for amcpso-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on razibmustafiz/AMC-PSO
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
amcpso-1.0.0-py3-none-any.whl -
Subject digest:
21d267fa6bb65dd77da9cbee66fc4781488b9eb4f1ceae3a5c8a0a9b66f72eed - Sigstore transparency entry: 2118827220
- Sigstore integration time:
-
Permalink:
razibmustafiz/AMC-PSO@da1ba7bfd290b7760419cf30b41c0781ae33a496 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/razibmustafiz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@da1ba7bfd290b7760419cf30b41c0781ae33a496 -
Trigger Event:
release
-
Statement type: