StochasticHillClimbingOptimizer.__init__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 27
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 24
dl 0
loc 27
rs 9.304
c 0
b 0
f 0
cc 1
nop 11

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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