Completed
Push — master ( 734fb3...5d2776 )
by Simon
04:12 queued 11s
created

TabuPositioner.add_tabu()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nop 2
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 ...base_positioner import BasePositioner
11
from scipy.spatial.distance import euclidean
12
13
14
def gaussian(distance, sig):
15
    return sig * np.exp(-np.power(distance, 2.0) / (2 * np.power(sig, 2.0)))
16
17
18
class TabuOptimizer(HillClimbingOptimizer):
19
    def __init__(self, *args, **kwargs):
20
        super().__init__(*args, **kwargs)
21
22
    def _tabu_pos(self, pos, _p_):
23
        _p_.add_tabu(pos)
24
25
        return _p_
26
27
    def _iterate(self, i, _cand_, _p_, X, y):
28
        _p_.pos_new = _p_.move_climb(_cand_, _p_.pos_current)
29
        _p_.score_new = _cand_.eval_pos(_p_.pos_new, X, y)
30
31
        if _p_.score_new > _cand_.score_best:
32
            _cand_, _p_ = self._update_pos(_cand_, _p_)
33
        else:
34
            _p_ = self._tabu_pos(_p_.pos_new, _p_)
35
36
        return _cand_
37
38
    def _init_opt_positioner(self, _cand_, X, y):
39
        return super()._init_base_positioner(
40
            _cand_, positioner=TabuPositioner, pos_para=self.pos_para
41
        )
42
43
44
class TabuPositioner(BasePositioner):
45
    def __init__(self, epsilon):
46
        super().__init__(epsilon)
47
        self.tabus = []
48
49
    def add_tabu(self, tabu):
50
        self.tabus.append(tabu)
51
52
    def move_climb(self, _cand_, pos, epsilon_mod=1):
53
        sigma = 3 + _cand_._space_.dim * self.epsilon * epsilon_mod
54
        pos_normal = np.random.normal(pos, sigma, pos.shape)
55
        pos_new_int = np.rint(pos_normal)
56
57
        for tabu in self.tabus:
58
            distance = euclidean(pos_new_int, tabu)
59
            sigma_mean = sigma.mean()
60
            p_discard = gaussian(distance, sigma_mean)
61
            rand = random.uniform(0, 1)
62
63
            if p_discard > rand:
64
                pos_normal = np.random.normal(pos, sigma, pos.shape)
65
                pos_new_int = np.rint(pos_normal)
66
67
        n_zeros = [0] * len(_cand_._space_.dim)
68
        pos = np.clip(pos_new_int, n_zeros, _cand_._space_.dim)
69
70
        return pos
71