Numerical Optimization

Numerical Optimization#

This notebook offers a step-by-step tutorial on utilizing EvoX to optimize the Ackley function through the Particle Swarm Optimization (PSO) algorithm. Both the PSO algorithm and the Ackley optimization problem are integrated as built-in components within the EvoX framework.

First, we should import all necessary modules including PSO (algorithm), Ackley (problem) and StdWorkflow & EvalMonitor (workflow).

import torch

from evox.algorithms.pso_variants import PSO
from evox.problems.numerical import Ackley
from evox.workflows import StdWorkflow, EvalMonitor

Here, we instantiate the PSO algorithm. We specify the following settings:

  • pop_size: The size of the particle swarm (population).

  • lb and ub: The lower and upper bounds for each dimension in the search space.

  • Other parameters are all default. Please refer to the detailed API.

# Define the algorithm
algorithm = PSO(pop_size=100, lb=-32 * torch.ones(10), ub=32 * torch.ones(10))

Next, we choose the Ackley function in EvoX’ s numerical problem.

# Define the problem
problem = Ackley()

We creat an EvalMonitor instance to track necessary information during the optimization procedure.

# Define the monitor
monitor = EvalMonitor()

The StdWorkflow class provides a standardized process to integrate the algorithm, problem, and monitor.

# Define the workflow
workflow = StdWorkflow()

Calling setup() initializes the components so that the workflow is ready to perform optimization steps.

# Set up the workflow with the defined algorithm, problem and monitor
workflow.setup(algorithm=algorithm, problem=problem, monitor=monitor)

We run the optimization for a certain number of iterations (100 in this example). In each iteration, the step() method updates the PSO algorithm, evaluates new candidate solutions on the Ackley function, and tracks their fitness via the monitor.

# Perform the Ackley function optimization procedure
for _ in range(100):
    workflow.step()

Finally, we retrieve the monitor submodule from the workflow to access the top solutions found so far (topk_solutions) and their corresponding objective values (topk_fitness). We then print the best result and the associated solution.

# Get the best solution and its fitness
monitor = workflow.get_submodule("monitor")
population = monitor.topk_solutions
fitness = monitor.topk_fitness
print(f"The best solution is:\n{population},\nwith the minimum value:\n{fitness}")
The best solution is:
tensor([[ 2.8948e-05, -9.1801e-05,  3.9575e-05,  2.3795e-05,  6.1906e-05,
         -1.1700e-04,  4.0033e-05,  4.3422e-05, -1.1519e-05, -2.7218e-05]]),
with the minimum value:
tensor([0.0002])
monitor.plot()