Skip to content

Commit 96f8453

Browse files
authored
Merge pull request #297 from malun22/PSO
Add PSOSampler
2 parents 69db17b + 19283be commit 96f8453

File tree

5 files changed

+536
-0
lines changed

5 files changed

+536
-0
lines changed

package/samplers/pso/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Luca Bernstiel
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

package/samplers/pso/README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
author: Luca Bernstiel
3+
title: Particle Swarm Optimization (PSO) Sampler
4+
description: Particle Swarm Optimization is a population-based stochastic optimization algorithm inspired by flocking behavior, where particles iteratively adjust their positions using personal and global bests to search for optima.
5+
tags: [sampler]
6+
optuna_versions: [4.5.0]
7+
license: MIT License
8+
---
9+
10+
## Abstract
11+
12+
Particle Swarm Optimization (PSO) is a population-based stochastic optimizer inspired by flocking behavior, where particles iteratively adjust their positions using personal and global bests to search for optima. This sampler supports single-objective, continuous optimization only.
13+
14+
> Note: Categorical distributions are suggested by the underlaying RandomSampler.
15+
16+
> Note: Multi-objective optimization is not supported.
17+
18+
For details on the algorithm, see Kennedy and Eberhart (1995): [Particle Swarm Optimization](https://doi.org/10.1109/ICNN.1995.488968).
19+
20+
## APIs
21+
22+
- `PSOSampler(search_space: dict[str, BaseDistribution] | None = None, n_particles: int = 10, inertia: float = 0.5, cognitive: float = 1.5, social: float = 1.5, seed: int | None = None)`
23+
- `search_space`: A dictionary containing the search space that defines the parameter space. The keys are the parameter names and the values are [the parameter's distribution](https://optuna.readthedocs.io/en/stable/reference/distributions.html). If the search space is not provided, the sampler will infer the search space dynamically.
24+
Example:
25+
```python
26+
search_space = {
27+
"x": optuna.distributions.FloatDistribution(-10, 10),
28+
"y": optuna.distributions.FloatDistribution(-10, 10),
29+
}
30+
PSOSampler(search_space=search_space)
31+
```
32+
- `n_particles`: Number of particles (population size). Prefer total n_trials to be a multiple of n_particles to run full PSO iterations. Larger swarms can improve exploration when budget allows.
33+
- `inertia`: Inertia weight controlling momentum (influence of previous velocity). Higher values favor exploration, lower favor exploitation.
34+
- `cognitive`: Personal-best acceleration coefficient (c1). Controls attraction toward each particle’s own best.
35+
- `social`: Global-best acceleration coefficient (c2). Controls attraction toward the swarm’s best.
36+
- `seed`: Seed for random number generator.
37+
38+
## Example
39+
40+
```python
41+
import optuna
42+
import optunahub
43+
44+
45+
def objective(trial: optuna.Trial) -> float:
46+
x = trial.suggest_float("x", -10, 10)
47+
y = trial.suggest_float("y", -10, 10)
48+
return x**2 + y**2
49+
50+
n_trials = 100
51+
n_generations = 5
52+
53+
sampler = optunahub.load_module(package="samplers/pso").PSOSampler(
54+
{
55+
"x": optuna.distributions.FloatDistribution(-10, 10),
56+
"y": optuna.distributions.FloatDistribution(-10, 10),
57+
},
58+
n_particles=int(n_trials / n_generations),
59+
inertia=0.5,
60+
cognitive=1.5,
61+
social=1.5,
62+
)
63+
64+
study = optuna.create_study(sampler=sampler)
65+
study.optimize(objective, n_trials=n_trials)
66+
print(study.best_trials)
67+
```

package/samplers/pso/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .sampler import PSOSampler
2+
3+
4+
__all__ = ["PSOSampler"]

package/samplers/pso/example.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from __future__ import annotations
2+
3+
import optuna
4+
import optunahub
5+
6+
7+
def objective(trial: optuna.Trial) -> float:
8+
x = trial.suggest_float("x", -10, 10)
9+
y = trial.suggest_float("y", -10, 10)
10+
return x**2 + y**2
11+
12+
13+
package_name = "samplers/pso"
14+
test_local = False
15+
16+
n_trials = 100
17+
n_generations = 5
18+
19+
if test_local:
20+
# This is an example of how to load a sampler from your local optunahub-registry.
21+
sampler = optunahub.load_local_module(
22+
package=package_name,
23+
registry_root="./package", # Path to the root of the optunahub-registry.
24+
).PSOSampler(
25+
{
26+
"x": optuna.distributions.FloatDistribution(-10, 10),
27+
"y": optuna.distributions.FloatDistribution(-10, 10),
28+
},
29+
n_particles=int(n_trials / n_generations),
30+
inertia=0.5,
31+
cognitive=1.5,
32+
social=1.5,
33+
)
34+
else:
35+
# This is an example of how to load a sampler from your fork of the optunahub-registry.
36+
sampler = optunahub.load_module(package=package_name).PSOSampler(
37+
{
38+
"x": optuna.distributions.FloatDistribution(-10, 10),
39+
"y": optuna.distributions.FloatDistribution(-10, 10),
40+
},
41+
n_particles=int(n_trials / n_generations),
42+
inertia=0.5,
43+
cognitive=1.5,
44+
social=1.5,
45+
)
46+
47+
study = optuna.create_study(sampler=sampler)
48+
study.optimize(objective, n_trials=n_trials)
49+
print(study.best_trials)

0 commit comments

Comments
 (0)