Completed
Push — master ( 1d68af...e525d3 )
by Simon
01:31
created

ParallelTemperingOptimizer._annealing_systems()   A

Complexity

Conditions 2

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 2
nop 3
1
# Author: Simon Blanke
2
# Email: [email protected]
3
# License: MIT License
4
5
6
import random
7
8
import numpy as np
9
10
from .simulated_annealing import SimulatedAnnealingOptimizer
11
from ..local import HillClimbingPositioner
12
13
14
class ParallelTemperingOptimizer(SimulatedAnnealingOptimizer):
15
    def __init__(self, _main_args_, _opt_args_):
16
        super().__init__(_main_args_, _opt_args_)
17
        self.n_iter_swap = int(self._main_args_.n_iter / self._opt_args_.n_swaps)
18
19
    def _init_annealers(self, _cand_):
20
        _p_list_ = [
21
            System(**self._opt_args_.kwargs_opt, temp=temp)
22
            for temp in self._opt_args_.system_temperatures
23
        ]
24
25
        for _p_ in _p_list_:
26
            _p_.pos_current = _cand_._space_.get_random_pos()
27
            _p_.pos_best = _p_.pos_current
28
29
        return _p_list_
30
31
    def _swap_pos(self, _cand_, _p_list_):
32
        _p_list_temp = _p_list_[:]
33
34
        for _p1_ in _p_list_:
35
            rand = random.uniform(0, 1)
36
            _p2_ = np.random.choice(_p_list_temp)
37
38
            p_accept = self._accept_swap(_p1_, _p2_)
39
            if p_accept > rand:
40
                temp_temp = _p1_.temp  # haha!
41
                _p1_.temp = _p2_.temp
42
                _p2_.temp = temp_temp
43
44
    def _accept_swap(self, _p1_, _p2_):
45
        denom = _p1_.score_current + _p2_.score_current
46
47
        if denom == 0:
48
            return 100
49
        elif abs(denom) == np.inf:
50
            return 0
51
        else:
52
            score_diff_norm = (_p1_.score_current - _p2_.score_current) / denom
53
54
            temp = (1 / _p1_.temp) - (1 / _p2_.temp)
55
            return np.exp(score_diff_norm * temp)
56
57
    def _anneal_system(self, _cand_, _p_):
58
        _cand_ = super()._iterate(0, _cand_, _p_)
59
60
        return _cand_
61
62
    def _iterate(self, i, _cand_, _p_list_):
63
        _p_current = _p_list_[i % len(_p_list_)]
64
        _cand_ = self._anneal_system(_cand_, _p_current)
65
66
        if self.n_iter_swap != 0 and i % self.n_iter_swap == 0:
67
            self._swap_pos(_cand_, _p_list_)
68
69
        return _cand_
70
71
    def _init_opt_positioner(self, _cand_):
72
        _p_list_ = self._init_annealers(_cand_)
73
74
        return _p_list_
75
76
77
class System(HillClimbingPositioner):
78
    def __init__(self, *args, **kwargs):
79
        super().__init__(*args, **kwargs)
80
        self.temp = kwargs["temp"]
81