File size: 2,796 Bytes
e75e97c
83ff599
 
 
 
e75e97c
 
c5bd69c
 
 
 
 
 
 
e75e97c
 
 
83ff599
e75e97c
 
 
 
 
c5bd69c
e75e97c
 
 
 
 
 
 
 
 
 
83ff599
c5bd69c
e75e97c
 
 
 
 
 
 
 
 
 
83ff599
 
 
 
 
 
 
 
 
 
 
 
 
e75e97c
 
 
 
 
 
 
 
 
 
83ff599
e75e97c
 
c5bd69c
 
 
 
e75e97c
 
 
c5bd69c
e75e97c
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import numpy as np
import matplotlib.pyplot as plt


DO_VIS = True


# in-place
def clip_params(population, clipper_function):
    for i, individual in enumerate(population):
        population[i] = clipper_function(individual)


def evolution_strategies_optimizer(objective_function, clipper_function, init_mean, init_scale):
    # Initialize parameters
    population_size = 100
    number_of_generations = 30
    mutation_scale = 0.05
    selection_ratio = 0.5
    selected_size = int(population_size * selection_ratio)

    # Initialize population (randomly)
    population = np.random.normal(loc=init_mean, scale=init_scale, size=(population_size, len(init_mean)))
    clip_params(population, clipper_function)

    for generation in range(number_of_generations):
        # Evaluate fitness
        fitness = np.array([objective_function(individual) for individual in population])
        
        # Select the best individuals
        selected_indices = np.argsort(fitness)[:selected_size]
        selected = population[selected_indices]
        
        # Reproduce (mutate)
        offspring = selected + np.random.normal(loc=0, scale=init_scale * mutation_scale, size=(selected_size, len(init_mean)))
        clip_params(offspring, clipper_function) # in-place
        
        # Replacement: Here we simply generate new candidates around the selected ones
        population[:selected_size] = selected
        population[selected_size:] = offspring
        
        # Logging
        best_fitness = fitness[selected_indices[0]]
        best_index = np.argmin(fitness)
        best_solution = population[best_index]
        print(f"Generation {generation + 1}: Best Fitness = {best_fitness}", f"Best solution so far: {best_solution}")
        if DO_VIS:
            plt.scatter(population[:, 0], population[:, 1])
            plt.xlim(-5, 5)
            plt.ylim(-5, 5)
            x = np.linspace(-5, 5, 100)
            y = np.linspace(-5, 5, 100)
            XY = np.stack(np.meshgrid(x, y), axis=-1)
            print(XY.shape)

            # Defining the function (x - 3)**2 + (y + 2)**2
            Z = toy_objective_function(XY)
            contour = plt.contour(XY[..., 0], XY[..., 1], Z, levels=50)
            plt.show()


    # Best solution
    best_index = np.argmin(fitness)
    best_solution = population[best_index]
    print(f"Best solution found: {best_solution}")
    return best_solution


def toy_objective_function(x):
    return (x[..., 0] - 3)**2 + (x[..., 1] + 2)**2


def toy_clipper_function(x):
    return x


def main():
    init_mean = np.array([0.0, 0.0])
    init_scale = np.array([10.0, 10.0])
    best_solution = evolution_strategies_optimizer(toy_objective_function, toy_clipper_function, init_mean, init_scale)


if __name__ == '__main__':
    main()