StochasticHillClimbingOptimizer._execute_transition()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
6
import numpy as np
7
from random import random
8
9
from . import HillClimbingOptimizer
10
from ..core_optimizer.parameter_tracker.stochastic_hill_climbing import (
11
    ParameterTracker,
12
)
13
14
15
class StochasticHillClimbingOptimizer(HillClimbingOptimizer, ParameterTracker):
16
    name = "Stochastic Hill Climbing"
17
    _name_ = "stochastic_hill_climbing"
18
    __name__ = "StochasticHillClimbingOptimizer"
19
20
    optimizer_type = "local"
21
    computationally_expensive = False
22
23
    def __init__(
24
        self,
25
        search_space,
26
        initialize={"grid": 4, "random": 2, "vertices": 4},
27
        constraints=[],
28
        random_state=None,
29
        rand_rest_p=0,
30
        nth_process=None,
31
        epsilon=0.03,
32
        distribution="normal",
33
        n_neighbours=3,
34
        p_accept=0.5,
35
    ):
36
        super().__init__(
37
            search_space=search_space,
38
            initialize=initialize,
39
            constraints=constraints,
40
            random_state=random_state,
41
            rand_rest_p=rand_rest_p,
42
            nth_process=nth_process,
43
            epsilon=epsilon,
44
            distribution=distribution,
45
            n_neighbours=n_neighbours,
46
        )
47
48
        self.p_accept = p_accept
49
        self.temp = 1
50
51
    @ParameterTracker.considered_transitions
52
    def _consider(self, p_accept):
53
        if p_accept >= random():
54
            self._execute_transition()
55
56
    @ParameterTracker.transitions
57
    def _execute_transition(self):
58
        self._new2current()
59
60
    @property
61
    def _normalized_energy_state(self):
62
        denom = self.score_current + self.score_new
63
64
        if denom == 0:
65
            return 1
66
        elif abs(denom) == np.inf:
67
            return 0
68
        else:
69
            return (self.score_new - self.score_current) / denom
70
71
    @property
72
    def _exponent(self):
73
        if self.temp == 0:
74
            return -np.inf
75
        else:
76
            return self._normalized_energy_state / self.temp
77
78
    def _p_accept_default(self):
79
        return self.p_accept * 2 / (1 + np.exp(self._exponent))
80
81
    @HillClimbingOptimizer.track_new_score
82
    def _transition(self, score_new):
83
        p_accept = self._p_accept_default()
84
        self._consider(p_accept)
85
86
    def evaluate(self, score_new):
87
        if score_new <= self.score_current:
88
            self._transition(score_new)
89
        else:
90
            HillClimbingOptimizer.evaluate(self, score_new)
91