Integer optimization¶
pso-rs optimizes integer variables with a deliberately simple approach:
the swarm always moves in a continuous internal space, and
discretization happens only at evaluation time (in SearchSpace::decode).
This keeps the central question of integer PSO — how do you discretize? —
explicit, and lets you compare strategies easily. It is
also why the core never needs generics over the position type: positions are
always Vec<f64> internally.
From Python¶
Pass integer=True. Bounds are still given as numbers; they are rounded to
integer limits.
import turboswarm as pso
# f(x) = (x0 - 3)^2 + (x1 + 2)^2, integer optimum at (3, -2).
r = pso.minimize(
lambda x: (x[0] - 3) ** 2 + (x[1] + 2) ** 2,
bounds=[(-10, 10)] * 2,
integer=True,
seed=5,
)
print(r.best_position) # [3.0, -2.0]
print(r.best_value) # 0.0
The objective receives already-decoded integer values. The returned
best_position corresponds to integer coordinates.
Binary variables¶
For {0, 1} problems (feature selection, knapsack, subset choice) pass
binary=True. It is the binary special case of the integer space; the
dimension is taken from bounds.
# 0/1 knapsack: pick items maximizing value within a weight cap.
values, weights, cap = [10, 13, 18, 31, 7, 15], [2, 3, 4, 7, 1, 3], 10
r = pso.minimize(
lambda x: -sum(v * xi for v, xi in zip(values, x)), # minimize -value
bounds=[(0, 1)] * len(values),
binary=True,
constraints=[lambda x: sum(w * xi for w, xi in zip(weights, x)) - cap],
n_particles=50, max_iter=200, seed=1,
)
chosen = [int(b) for b in r.best_position]
Mixed variable types¶
Real problems often mix continuous, integer and binary variables. Pass
var_types — one of "real", "integer" or "binary" per dimension (same
length as bounds):
# x0 continuous, x1 integer, x2 binary.
r = pso.minimize(
lambda x: (x[0] - 1.5) ** 2 + (x[1] - 3) ** 2 + (x[2] - 1) ** 2,
bounds=[(-5, 5), (-10, 10), (0, 1)],
var_types=["real", "integer", "binary"],
seed=7,
)
# r.best_position == [1.5, 3.0, 1.0] (integer/binary dims are whole-valued)
Integer and binary dimensions come back as whole-valued floats. var_types
takes precedence over the integer / binary flags. In Rust this is the
MixedSpace (its Scalar is f64).
Discretization strategies (Rust)¶
From Rust, IntegerSpace supports three strategies via with_discretization:
Round— nearest integer (default, most common).Truncate— toward zero.Floor— round down.
use turboswarm_core::prelude::*;
let space = IntegerSpace::new(vec![(-10, 10); 2])
.with_discretization(Discretization::Floor);
Comparing how the chosen strategy affects convergence on the same problem is a compact way to compare them.