Global minimization of a non-expensive scalar function

Driver:

DifferentialEvolution

Download script:

differential_evolution.py

The target of the study is to minimize a scalar function. The scalar function is assumed to be inexpensive to evaluate (i.e. evaluation time shorter than a second) and to have no known derivatives. In this case a heuristic global optimization is advisable. Differential evolution (DE) is an evolutionary optimization algorithm inspired by the mutation, crossover and selection processes occurring in nature.

As an example, the 2D Rastrigin function on a circular domain is minimized,

\[ \begin{align}\begin{aligned}&\text{min.}\,& f(x_1,x_2) = 2\cdot10 + \sum_{i=1,2} \left(x_i^2 - 10\cos(2\pi x_i)\right)\\&\text{s.t.}\,& \sqrt{x_1^2 + x_2^2} \leq 1.5.\end{aligned}\end{align} \]
 1import sys,os
 2import numpy as np
 3import time
 4
 5from jcmoptimizer import Client, Study, Obseravtion
 6client = Client()
 7
 8
 9# Definition of the search domain
10design_space = [
11    {'name': 'x1', 'type': 'continuous', 'domain': (-1.5,1.5)}, 
12    {'name': 'x2', 'type': 'continuous', 'domain': (-1.5,1.5)},
13]
14
15# Definition of fixed environment parameter
16environment = [
17    {'name': 'radius', 'type': 'fixed', 'domain': 1.5},
18]
19
20# Definition of a constraint on the search domain
21constraints = [
22    {'name': 'circle', 'expression': 'sqrt(x1^2 + x2^2) <= radius'}
23]
24
25# Creation of the study object with study_id 'differential_evolution'
26study = client.create_study(
27    design_space=design_space,
28    environment=environment,
29    constraints=constraints,
30    driver="DifferentialEvolution",
31    study_name="Global minimization of a non-expensive scalar function",
32    study_id="differential_evolution"
33)
34
35# Configure study parameters
36study.configure(max_iter=80, num_parallel=2)
37
38# Evaluation of the black-box function for specified design parameters
39def evaluate(study: Study, x1: float, x2: float, radius: float) -> Observation:
40
41    observation = study.new_observation()
42    observation.add(10*2
43                + (x1**2-10*np.cos(2*np.pi*x1)) 
44                + (x2**2-10*np.cos(2*np.pi*x2))
45            )
46    return observation
47
48# Run the minimization
49study.set_evaluator(evaluate)
50study.run()
51best = study.driver.best_sample
52print(f"Best sample at: x1={best['x1']:.3f}, x2={best['x2']:.3f}")
53
54client.shutdown_server()