Completed
Push — master ( ce1e03...f67568 )
by Simon
14:21
created

hyperactive.search.Search._run_multiple_jobs()   A

Complexity

Conditions 3

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
import time
6
import numpy as np
7
import multiprocessing
8
9
from .verbosity import set_verbosity
10
11
from .candidate import Candidate
12
13
14
from .optimizers import (
15
    HillClimbingOptimizer,
16
    StochasticHillClimbingOptimizer,
17
    TabuOptimizer,
18
    RandomSearchOptimizer,
19
    RandomRestartHillClimbingOptimizer,
20
    RandomAnnealingOptimizer,
21
    SimulatedAnnealingOptimizer,
22
    StochasticTunnelingOptimizer,
23
    ParallelTemperingOptimizer,
24
    ParticleSwarmOptimizer,
25
    EvolutionStrategyOptimizer,
26
    BayesianOptimizer,
27
    TreeStructuredParzenEstimators,
28
    DecisionTreeOptimizer,
29
)
30
31
optimizer_dict = {
32
    "HillClimbing": HillClimbingOptimizer,
33
    "StochasticHillClimbing": StochasticHillClimbingOptimizer,
34
    "TabuSearch": TabuOptimizer,
35
    "RandomSearch": RandomSearchOptimizer,
36
    "RandomRestartHillClimbing": RandomRestartHillClimbingOptimizer,
37
    "RandomAnnealing": RandomAnnealingOptimizer,
38
    "SimulatedAnnealing": SimulatedAnnealingOptimizer,
39
    "StochasticTunneling": StochasticTunnelingOptimizer,
40
    "ParallelTempering": ParallelTemperingOptimizer,
41
    "ParticleSwarm": ParticleSwarmOptimizer,
42
    "EvolutionStrategy": EvolutionStrategyOptimizer,
43
    "Bayesian": BayesianOptimizer,
44
    "TPE": TreeStructuredParzenEstimators,
45
    "DecisionTree": DecisionTreeOptimizer,
46
}
47
48
49
class Search:
50
    def __init__(self, _main_args_, _opt_args_):
51
        self._main_args_ = _main_args_
52
        self._opt_args_ = _opt_args_
53
54
        self._info_, _pbar_ = set_verbosity(_main_args_.verbosity)
55
        self._pbar_ = _pbar_()
56
57
        self.optimizer = optimizer_dict[self._main_args_.optimizer](_opt_args_)
58
59
        self.optimizer._pbar_ = self._pbar_
60
61
    def search(self, nth_process=0, rayInit=False):
62
        self.start_time = time.time()
63
        self.results = {}
64
        self.eval_times = {}
65
        self.iter_times = {}
66
        self.best_scores = {}
67
        self.pos_list = {}
68
        self.score_list = {}
69
70
        if rayInit:
71
            self._run_job(nth_process)
72
        elif self._main_args_.n_jobs == 1:
73
            self._run_job(nth_process)
74
        else:
75
            self._run_multiple_jobs()
76
77
        return (
78
            self.results,
79
            self.pos_list,
80
            self.score_list,
81
            self.eval_times,
82
            self.iter_times,
83
            self.best_scores,
84
        )
85
86
    def _search_multiprocessing(self):
87
        """Wrapper for the parallel search. Passes integer that corresponds to process number"""
88
        pool = multiprocessing.Pool(self._main_args_.n_jobs)
89
        _cand_list, _p_list = zip(
90
            *pool.map(self._search, self._main_args_._n_process_range)
91
        )
92
93
        return _cand_list, _p_list
94
95
    def _run_job(self, nth_process):
96
        _cand_, _p_ = self._search(nth_process)
97
        self._get_attributes(_cand_, _p_)
98
99
    def _get_attributes(self, _cand_, _p_):
100
        self.results[_cand_.func_] = _cand_._process_results(self._opt_args_)
101
        self.eval_times[_cand_.func_] = _cand_.eval_time
102
        self.iter_times[_cand_.func_] = _cand_.iter_times
103
        self.best_scores[_cand_.func_] = _cand_.score_best
104
105
        if isinstance(_p_, list):
106
            self.pos_list[_cand_.func_] = [np.array(p.pos_list) for p in _p_]
107
            self.score_list[_cand_.func_] = [np.array(p.score_list) for p in _p_]
108
        else:
109
            self.pos_list[_cand_.func_] = [np.array(_p_.pos_list)]
110
            self.score_list[_cand_.func_] = [np.array(_p_.score_list)]
111
112
    def _run_multiple_jobs(self):
113
        _cand_list, _p_list = self._search_multiprocessing()
114
115
        for _ in range(int(self._main_args_.n_jobs / 2) + 2):
116
            print("\n")
117
118
        for _cand_, _p_ in zip(_cand_list, _p_list):
119
            self._get_attributes(_cand_, _p_)
120
121
    def _search(self, nth_process):
122
        _cand_ = self._initialize_search(self._main_args_, nth_process, self._info_)
123
124
        for i in range(self._main_args_.n_iter):
125
            c_time = time.time()
126
127
            _cand_.i = i
128
            _cand_ = self.optimizer.iterate(i, _cand_)
129
130
            if self._time_exceeded():
131
                break
132
133
            _cand_.iter_times.append(time.time() - c_time)
134
135
        self.optimizer._finish_search()
136
137
        return _cand_, self.optimizer.p_list
138
139
    def _time_exceeded(self):
140
        run_time = time.time() - self.start_time
141
        return self._main_args_.max_time and run_time > self._main_args_.max_time
142
143
    def _initialize_search(self, _main_args_, nth_process, _info_):
144
        _main_args_._set_random_seed(nth_process)
145
146
        _cand_ = Candidate(nth_process, _main_args_, _info_)
147
        self._pbar_.init_p_bar(nth_process, self._main_args_)
148
149
        return _cand_
150