Passed
Push — master ( d39371...69bf6f )
by Simon
03:38
created

TabuOptimizer._move_climb()   A

Complexity

Conditions 4

Size

Total Lines 33
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 24
nop 3
dl 0
loc 33
rs 9.304
c 0
b 0
f 0
1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
import random
6
import numpy as np
7
8
9
from . import HillClimbingOptimizer
10
from ...search import Search
11
from scipy.spatial.distance import euclidean
12
13
14
def gaussian(distance, sig, sigma_factor=1):
15
    return (
16
        sigma_factor
17
        * sig
18
        * np.exp(-np.power(distance, 2.0) / (sigma_factor * np.power(sig, 2.0)))
19
    )
20
21
22
class TabuOptimizer(HillClimbingOptimizer, Search):
23
    def __init__(self, search_space, tabu_memory=3):
24
        super().__init__(search_space)
25
26
        self.tabus = []
27
        self.tabu_memory = tabu_memory
28
29
    def add_tabu(self, tabu):
30
        self.tabus.append(tabu)
31
32
        if len(self.tabus) > self.tabu_memory:
33
            self.tabus.pop(0)
34
35
    def _move_climb(self, pos, epsilon_mod=1):
36
        sigma = 1 + self.space_dim * self.epsilon * epsilon_mod
37
        pos_normal = np.random.normal(pos, sigma, pos.shape)
38
        pos_new_int = np.rint(pos_normal)
39
40
        sigma_mod = 1
41
        run = True
42
        while run:
43
            pos_normal = np.random.normal(pos, sigma * sigma_mod, pos.shape)
44
            pos_new_int = np.rint(pos_normal)
45
46
            p_discard_sum = []
47
            for tabu in self.tabus:
48
                distance = euclidean(pos_new_int, tabu)
49
                sigma_mean = sigma.mean()
50
                p_discard = gaussian(distance, sigma_mean)
51
52
                p_discard_sum.append(p_discard)
53
54
            p_discard = np.array(p_discard_sum).sum()
55
            rand = random.uniform(0, 1)
56
57
            if p_discard < rand:
58
                run = False
59
60
            sigma_mod = sigma_mod * 1.01
61
62
        n_zeros = [0] * len(self.space_dim)
63
        pos = np.clip(pos_new_int, n_zeros, self.space_dim)
64
65
        self.pos_new = pos.astype(int)
66
67
        return self.pos_new
68
69
    def evaluate(self, score_new):
70
        super().evaluate(score_new)
71
72
        if score_new < self.score_best:
73
            self.add_tabu(self.pos_new)
74
75