Passed
Push — master ( 82152a...125377 )
by Simon
04:39
created

LipschitzFunction.calculate()   A

Complexity

Conditions 1

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 11
nop 4
dl 0
loc 16
rs 9.85
c 0
b 0
f 0
1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
import numpy as np
6
7
from ..smb_opt.smbo import SMBO
8
from ...search import Search
9
10
from scipy.spatial.distance import cdist
11
12
13
class LipschitzFunction:
14
    def __init__(self, position_l):
15
        self.position_l = position_l
16
17
    def find_best_slope(self, X_sample, Y_sample):
18
        slopes = [
19
            abs(y_sample1 - y_sample2) / abs(x_sample1 - x_sample2)
20
            for x_sample1, y_sample1 in zip(X_sample, Y_sample)
21
            for x_sample2, y_sample2 in zip(X_sample, Y_sample)
22
            if y_sample1 is not y_sample2
23
            if np.prod((x_sample1 - x_sample2)) != 0
24
        ]
25
26
        if len(slopes) == 0:
27
            return 1
28
        return np.max(slopes)
29
30
    def calculate(self, X_sample, Y_sample, score_best):
31
        lip_c = self.find_best_slope(X_sample, Y_sample)
32
33
        positions_np = np.array(self.position_l)
34
        samples_np = np.array(X_sample)
35
36
        pos_dist = cdist(positions_np, samples_np) * lip_c
37
38
        upper_bound_l = pos_dist
39
        upper_bound_l += np.array(Y_sample)
40
41
        mx = np.ma.masked_array(upper_bound_l, mask=upper_bound_l == 0)
42
        upper_bound_l = mx.min(1).reshape(1, -1).T
43
        upper_bound_l[upper_bound_l <= score_best] = -np.inf
44
45
        return upper_bound_l
46
47
48
class LipschitzOptimizer(SMBO, Search):
49
    name = "Lipschitz Optimizer"
50
    _name_ = "lipschitz_optimizer"
51
52
    def __init__(self, *args, **kwargs):
53
        super().__init__(*args, **kwargs)
54
55
    @SMBO.track_new_pos
56
    @SMBO.track_X_sample
57
    def iterate(self):
58
        all_pos_comb = self._all_possible_pos()
59
        self.pos_comb = self._sampling(all_pos_comb)
60
61
        lip_func = LipschitzFunction(self.pos_comb)
62
        upper_bound_l = lip_func.calculate(
63
            self.X_sample, self.Y_sample, self.score_best
64
        )
65
66
        index_best = list(upper_bound_l.argsort()[::-1])
67
        all_pos_comb_sorted = self.pos_comb[index_best]
68
        pos_best = all_pos_comb_sorted[0]
69
70
        return pos_best
71