gradient_free_optimizers.optimizers.core_optimizer.init_positions   B
last analyzed

Complexity

Total Complexity 44

Size/Duplication

Total Lines 169
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 122
dl 0
loc 169
rs 8.8798
c 0
b 0
f 0
wmc 44

11 Methods

Rating   Name   Duplication   Size   Complexity  
A Initializer.set_pos() 0 20 5
A Initializer._init_warm_start() 0 13 4
A Initializer._get_random_vertex() 0 12 4
A Initializer.__init__() 0 17 5
A Initializer.get_n_inits() 0 9 3
A Initializer.move_random() 0 2 1
A Initializer.add_n_random_init_pos() 0 5 2
A Initializer._init_random_search() 0 14 5
B Initializer._init_grid_search() 0 27 6
A Initializer._fill_rest_random() 0 8 2
B Initializer._init_vertices() 0 20 7

How to fix   Complexity   

Complexity

Complex classes like gradient_free_optimizers.optimizers.core_optimizer.init_positions often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
import random
6
import numpy as np
7
8
from .utils import move_random
9
10
11
class Initializer:
12
    def __init__(self, conv, initialize):
13
        self.conv = conv
14
        self.initialize = initialize
15
16
        self.n_inits = 0
17
        if "random" in initialize:
18
            self.n_inits += initialize["random"]
19
        if "grid" in initialize:
20
            self.n_inits += initialize["grid"]
21
        if "vertices" in initialize:
22
            self.n_inits += initialize["vertices"]
23
        if "warm_start" in initialize:
24
            self.n_inits += len(initialize["warm_start"])
25
26
        self.init_positions_l = None
27
28
        self.set_pos()
29
30
    def move_random(self):
31
        return move_random(self.conv.search_space_positions)
32
33
    def add_n_random_init_pos(self, n):
34
        for _ in range(n):
35
            self.init_positions_l.append(self.move_random())
36
37
        self.n_inits = len(self.init_positions_l)
38
39
    def get_n_inits(initialize):
40
        n_inits = 0
41
        for key_ in initialize.keys():
42
            init_value = initialize[key_]
43
            if isinstance(init_value, int):
44
                n_inits += init_value
45
            else:
46
                n_inits += len(init_value)
47
        return n_inits
48
49
    def set_pos(self):
50
        init_positions_ll = []
51
52
        if "random" in self.initialize:
53
            positions = self._init_random_search(self.initialize["random"])
54
            init_positions_ll.append(positions)
55
        if "grid" in self.initialize:
56
            positions = self._init_grid_search(self.initialize["grid"])
57
            init_positions_ll.append(positions)
58
        if "vertices" in self.initialize:
59
            positions = self._init_vertices(self.initialize["vertices"])
60
            init_positions_ll.append(positions)
61
        if "warm_start" in self.initialize:
62
            positions = self._init_warm_start(self.initialize["warm_start"])
63
            init_positions_ll.append(positions)
64
65
        self.init_positions_l = [
66
            item for sublist in init_positions_ll for item in sublist
67
        ]
68
        self.init_positions_l = self._fill_rest_random(self.init_positions_l)
69
70
    def _init_warm_start(self, value_list):
71
        positions = []
72
73
        for value_ in value_list:
74
            pos = self.conv.value2position(list(value_.values()))
75
            positions.append(pos)
76
77
        positions_constr = []
78
        for pos in positions:
79
            if self.conv.not_in_constraint(pos):
80
                positions_constr.append(pos)
81
82
        return positions_constr
83
84
    def _init_random_search(self, n_pos):
85
        positions = []
86
87
        if n_pos == 0:
88
            return positions
89
90
        for nth_pos in range(n_pos):
91
            while True:
92
                pos = move_random(self.conv.search_space_positions)
93
                if self.conv.not_in_constraint(pos):
94
                    positions.append(pos)
95
                    break
96
97
        return positions
98
99
    def _fill_rest_random(self, positions):
100
        diff_pos = self.n_inits - len(positions)
101
        if diff_pos > 0:
102
            pos_rnd = self._init_random_search(n_pos=diff_pos)
103
104
            return positions + pos_rnd
105
        else:
106
            return positions
107
108
    def _init_grid_search(self, n_pos):
109
        positions = []
110
111
        if n_pos == 0:
112
            return positions
113
114
        n_dim = len(self.conv.max_positions)
115
        if n_dim > 30:
116
            positions = []
117
        else:
118
            p_per_dim = int(np.power(n_pos, 1 / n_dim))
119
120
            for dim in self.conv.max_positions:
121
                dim_dist = int(dim / (p_per_dim + 1))
122
                n_points = [n * dim_dist for n in range(1, p_per_dim + 1)]
123
124
                positions.append(n_points)
125
126
            pos_mesh = np.array(np.meshgrid(*positions))
127
            positions = list(pos_mesh.T.reshape(-1, n_dim))
128
129
        positions_constr = []
130
        for pos in positions:
131
            if self.conv.not_in_constraint(pos):
132
                positions_constr.append(pos)
133
134
        return positions_constr
135
136
    def _get_random_vertex(self):
137
        vertex = []
138
        for dim_positions in self.conv.search_space_positions:
139
            rnd = random.randint(0, 1)
140
141
            if rnd == 0:
142
                dim_pos = dim_positions[0]
143
            elif rnd == 1:
144
                dim_pos = dim_positions[-1]
145
146
            vertex.append(dim_pos)
0 ignored issues
show
introduced by
The variable dim_pos does not seem to be defined for all execution paths.
Loading history...
147
        return np.array(vertex)
148
149
    def _init_vertices(self, n_pos):
150
        positions = []
151
        for _ in range(n_pos):
152
            for _ in range(100):
153
                vertex = self._get_random_vertex()
154
155
                vert_in_list = any((vertex == pos).all() for pos in positions)
156
                if not vert_in_list:
157
                    positions.append(vertex)
158
                    break
159
            else:
160
                pos = move_random(self.conv.search_space_positions)
161
                positions.append(pos)
162
163
        positions_constr = []
164
        for pos in positions:
165
            if self.conv.not_in_constraint(pos):
166
                positions_constr.append(pos)
167
168
        return positions_constr
169