A Funz algorithm plugin implementing Particle Swarm Optimization (PSO) in R.
This repository provides the PSO algorithm for the fz framework, ported from the original algorithm-PSO Funz plugin.
Algorithm reference: Clerc, M. et al. (2010) Particle Swarm Optimization
The algorithm implements the fz R algorithm interface:
PSO(...): S3 constructor accepting algorithm-specific optionsget_initial_design.PSO(obj, input_variables, output_variables): Return initial swarm of particlesget_next_design.PSO(obj, X, Y): Update velocities and positions, return next swarm, orlist()when max iterations reachedget_analysis.PSO(obj, X, Y): Return optimum value, location, and optional visualizationget_analysis_tmp.PSO(obj, X, Y): Return intermediate progress (current iteration, best value)
-
Initialization: Creates a swarm of
nparticlesparticles randomly distributed in the input space, with random initial velocities. -
Iteration: At each iteration:
- Updates personal best positions (each particle remembers its best location)
- Updates global best (the best position found by any particle)
- Updates velocities using inertia, cognitive (personal best), and social (global best) components
- Updates positions and clamps to bounds with velocity reset
-
Convergence: Stops when:
- Maximum iterations reached
- R must be installed on your system
- rpy2 Python package:
pip install rpy2 - fz framework:
pip install git+https://github.com/Funz/fz.git
pip install git+https://github.com/Funz/fz.git
pip install rpy2import fz
fz.install_algorithm("PSO")Or from a URL:
fz.install_algorithm("https://github.com/Funz/fz-PSO")Or using the CLI:
fz install PSO| Option | Type | Default | Description |
|---|---|---|---|
yminimization |
boolean | true |
Minimize output value? Set to false for maximization |
max_iterations |
integer | 30 |
Maximum number of iterations |
nparticles |
integer | NA (auto) |
Number of particles in swarm (default: 10 + 2*sqrt(d) where d = number of dimensions) |
seed |
integer | 123 |
Random seed for reproducibility |
w |
numeric | 0.7213 |
Inertia weight (1/(2*log(2))) |
c_p |
numeric | 1.1931 |
Cognitive (personal best) coefficient (0.5+log(2)) |
c_g |
numeric | 1.1931 |
Social (global best) coefficient (0.5+log(2)) |
You can test the algorithm without any simulation code, using rpy2 directly:
from rpy2 import robjects
# Source the R algorithm
robjects.r.source(".fz/algorithms/PSO.R")
r_globals = robjects.globalenv
# Create an instance
r_algo = robjects.r["PSO"](
yminimization=True, max_iterations=20,
nparticles=15, seed=123
)
# Define input variable ranges as R list
r_input_vars = robjects.r('list(x1 = c(0.0, 1.0), x2 = c(0.0, 1.0))')
r_output_vars = robjects.StrVector(["output"])
# Get initial design (swarm of particles)
r_design = r_globals['get_initial_design'](r_algo, r_input_vars, r_output_vars)
print(f"Initial design: {len(r_design)} particles")Or via fz's automatic wrapper:
from fz.algorithms import load_algorithm
# Load R algorithm (fz handles rpy2 wrapping automatically)
algo = load_algorithm("PSO",
yminimization=True, max_iterations=20, nparticles=15)
# Same Python interface as Python algorithms
design = algo.get_initial_design(
{"x1": (0.0, 1.0), "x2": (0.0, 1.0)}, ["output"]
)
print(f"Initial design: {len(design)} particles")Use fz.fzd() to run the algorithm coupled with a model and calculators:
import fz
# Install model and algorithm plugins
fz.install("Model")
fz.install_algorithm("PSO")
# Run optimization
analysis = fz.fzd(
input_path="examples/Model/input.txt",
input_variables={"x": "[0;10]", "y": "[-5;5]"},
model="Model",
output_expression="result",
algorithm="PSO",
algorithm_options={
"yminimization": True,
"max_iterations": 30,
"nparticles": 20,
"seed": 123
},
calculators="localhost_Model",
analysis_dir="analysis_results_pso"
)
print(analysis)The algorithm provides:
-
Final analysis:
- Optimum value found
- Location of optimum (input values)
- Number of iterations and evaluations
- Swarm size used
- Visualization plot (pairs plot for multi-dimensional, scatter plot for 1D)
-
Intermediate progress:
- Current iteration number
- Current best value
- Number of evaluations so far
fz-PSO/
├── .fz/
│ └── algorithms/
│ └── PSO.R # R algorithm implementation (S3 class)
├── .github/
│ └── workflows/
│ └── test.yml # CI workflow (includes R setup)
├── tests/
│ └── test_plugin.py # Test suite (uses rpy2)
├── example_standalone.ipynb # Notebook: algorithm without fzd
├── example_with_fzd.ipynb # Notebook: algorithm with fzd
├── LICENSE
└── README.md
- Type: Global optimization
- Order: Zero-order (derivative-free)
- Method: Particle Swarm Optimization (SPSO 2007-style velocity update)
- Base R (no special packages required)
- Optional:
base64encfor HTML visualization output
This algorithm has been ported from the original Funz plugin format to the new fz format:
- Original: algorithm-PSO
Key changes from old format:
- Constructor pattern using S3 classes instead of environments
- Methods renamed:
getInitialDesign→get_initial_design,getNextDesign→get_next_design, etc. - Removed
future/templrasync dependency — now uses synchronous step-by-step interface - Input/output format adapted to new fz expectations (list of points instead of matrices)
- Return empty
list()to signal completion instead ofNULL - State management using environments for mutable state
- Simplified PSO core: inertia + cognitive + social velocity update with boundary clamping
# Run all tests
python -m pytest tests/ -v
# Or directly
python tests/test_plugin.pyBSD 3-Clause License (same as original Funz project)
Yann Richet, Claus Bendtsen (ported to new fz format)