Passed
Push — master ( b8f359...927840 )
by Simon
03:10
created

hyperactive.hyperactive.Hyperactive.results()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
6
import multiprocessing
7
from tqdm import tqdm
8
9
from .optimizers import RandomSearchOptimizer
10
from .run_search import run_search
11
12
13
def set_n_jobs(n_jobs):
14
    """Sets the number of jobs to run in parallel"""
15
    num_cores = multiprocessing.cpu_count()
16
    if n_jobs == -1 or n_jobs > num_cores:
17
        return num_cores
18
    else:
19
        return n_jobs
20
21
22
class HyperactiveResults:
23
    def __init__(*args, **kwargs):
24
        pass
25
26
    def _sort_results_objFunc(self, objective_function):
27
        import numpy as np
28
        import pandas as pd
29
30
        best_score = -np.inf
31
        best_para = None
32
        results_list = []
33
34
        for results in self.results_list:
35
            nth_process = results["nth_process"]
36
37
            process_infos = self.process_infos[nth_process]
38
            objective_function_ = process_infos["objective_function"]
39
40
            if objective_function_ != objective_function:
41
                continue
42
43
            if results["best_score"] > best_score:
44
                best_score = results["best_score"]
45
                best_para = results["best_para"]
46
47
            results_list.append(results["results"])
48
49
        results = pd.concat(results_list)
50
51
        self.objFunc2results[objective_function] = {
52
            "best_para": best_para,
53
            "best_score": best_score,
54
            "results": results,
55
        }
56
57
    def _sort_results_search_id(self, search_id):
58
        for results in self.results_list:
59
            nth_process = results["nth_process"]
60
            search_id_ = self.process_infos[nth_process]["search_id"]
61
62
            if search_id_ != search_id:
63
                continue
64
65
            best_score = results["best_score"]
66
            best_para = results["best_para"]
67
            results = results["results"]
68
69
            self.search_id2results[search_id] = {
70
                "best_para": best_para,
71
                "best_score": best_score,
72
                "results": results,
73
            }
74
75
    def _get_one_result(self, id_, result_name):
76
        if isinstance(id_, str):
77
            if id_ not in self.search_id2results:
78
                self._sort_results_search_id(id_)
79
80
            return self.search_id2results[id_][result_name]
81
82
        else:
83
            if id_ not in self.objFunc2results:
84
                self._sort_results_objFunc(id_)
85
86
            return self.objFunc2results[id_][result_name]
87
88
    def best_para(self, id_):
89
        return self._get_one_result(id_, "best_para")
90
91
    def best_score(self, id_):
92
        return self._get_one_result(id_, "best_score")
93
94
    def results(self, id_):
95
        return self._get_one_result(id_, "results")
96
97
98
class HyperactiveLongTermMemory:
99
    def __init__(*args, **kwargs):
100
        pass
101
102
    def _load_ltm(self, memory_warm_start):
103
        if self.long_term_memory is not None:
104
            return self.long_term_memory.load()
105
        else:
106
            return memory_warm_start
107
108
    def _save_ltm(self):
109
        for nth_process in self.process_infos.keys():
110
            long_term_memory = self.process_infos[nth_process]["long_term_memory"]
111
            objective_function = self.process_infos[nth_process]["objective_function"]
112
            memory_results = self.results_list[nth_process]["memory_values_df"]
113
114
            if long_term_memory is not None:
115
                long_term_memory.save(memory_results, objective_function)
116
117
118
class Hyperactive(HyperactiveResults, HyperactiveLongTermMemory):
119
    def __init__(
120
        self,
121
        verbosity=["progress_bar", "print_results", "print_times"],
122
        distribution={
123
            "multiprocessing": {
124
                "initializer": tqdm.set_lock,
125
                "initargs": (tqdm.get_lock(),),
126
            }
127
        },
128
    ):
129
        super().__init__()
130
        if verbosity is False:
131
            verbosity = []
132
133
        self.verbosity = verbosity
134
        self.distribution = distribution
135
        self.search_ids = []
136
137
        self.process_infos = {}
138
139
        self.objFunc2results = {}
140
        self.search_id2results = {}
141
142
    def _add_search_processes(
143
        self,
144
        random_state,
145
        objective_function,
146
        search_space,
147
        optimizer,
148
        n_iter,
149
        n_jobs,
150
        max_score,
151
        memory,
152
        memory_warm_start,
153
        long_term_memory,
154
        search_id,
155
    ):
156
        for nth_job in range(set_n_jobs(n_jobs)):
157
            nth_process = len(self.process_infos)
158
159
            self.process_infos[nth_process] = {
160
                "random_state": random_state,
161
                "verbosity": self.verbosity,
162
                "nth_process": nth_process,
163
                "objective_function": objective_function,
164
                "search_space": search_space,
165
                "optimizer": optimizer,
166
                "n_iter": n_iter,
167
                "max_score": max_score,
168
                "memory": memory,
169
                "memory_warm_start": memory_warm_start,
170
                "long_term_memory": long_term_memory,
171
                "search_id": search_id,
172
            }
173
174
    def add_search(
175
        self,
176
        objective_function,
177
        search_space,
178
        n_iter,
179
        search_id=None,
180
        optimizer="default",
181
        n_jobs=1,
182
        initialize={"grid": 4, "random": 2, "vertices": 4},
183
        max_score=None,
184
        random_state=None,
185
        memory=True,
186
        memory_warm_start=None,
187
        long_term_memory=None,
188
    ):
189
        self.long_term_memory = long_term_memory
190
191
        if isinstance(optimizer, str):
192
            if optimizer == "default":
193
                optimizer = RandomSearchOptimizer()
194
        optimizer.init(search_space, initialize)
195
196
        if search_id is not None:
197
            search_id = search_id
198
            self.search_ids.append(search_id)
199
        else:
200
            search_id = str(len(self.search_ids))
201
            self.search_ids.append(search_id)
202
203
        memory_warm_start = self._load_ltm(memory_warm_start)
204
205
        self._add_search_processes(
206
            random_state,
207
            objective_function,
208
            search_space,
209
            optimizer,
210
            n_iter,
211
            n_jobs,
212
            max_score,
213
            memory,
214
            memory_warm_start,
215
            long_term_memory,
216
            search_id,
217
        )
218
219
    def run(
220
        self,
221
        max_time=None,
222
    ):
223
        for nth_process in self.process_infos.keys():
224
            self.process_infos[nth_process]["max_time"] = max_time
225
226
        self.results_list = run_search(self.process_infos, self.distribution)
227
228
        self._save_ltm()
229