Passed
Pull Request — master (#110)
by
unknown
01:27
created

hyperactive.opt.gfo.hillclimbing   A

Complexity

Total Complexity 5

Size/Duplication

Total Lines 127
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 45
dl 0
loc 127
rs 10
c 0
b 0
f 0
wmc 5

4 Methods

Rating   Name   Duplication   Size   Complexity  
A HillClimbing.add_search() 0 21 1
A HillClimbing.__init__() 0 30 2
A HillClimbing.get_search_config() 0 10 1
A HillClimbing._run() 0 21 1
1
"""Hill climbing optimizer from gfo."""
2
3
from gradient_free_optimizers import HillClimbingOptimizer
4
from hyperactive.base import BaseOptimizer
5
6
7
class HillClimbing(BaseOptimizer):
8
    """Hill climbing optimizer.
9
10
    Parameters
11
    ----------
12
    experiment : BaseExperiment, optional
13
        The experiment to optimize parameters for.
14
        Optional, can be passed later in ``add_search``.
15
    random_state : None, int, default=None
16
        If None, create a new random state. If int, create a new random state
17
        seeded with the value.
18
    rand_rest_p : float, default=0.1
19
        The probability of a random iteration during the the search process.
20
    epsilon : float, default=0.01
21
        The step-size for the climbing.
22
    distribution : str, default="uniform"
23
        The type of distribution to sample from.
24
    n_neighbours : int, default=10
25
        The number of neighbours to sample and evaluate before moving to the best
26
        of those neighbours.
27
    search_space : dict[str, list]
28
        The search space to explore. A dictionary with parameter
29
        names as keys and a numpy array as values.
30
        Optional, can be passed later in ``add_search``.
31
    initialize : dict[str, int], default={"grid": 4, "random": 2, "vertices": 4}
32
        The method to generate initial positions. A dictionary with
33
        the following key literals and the corresponding value type:
34
        {"grid": int, "vertices": int, "random": int, "warm_start": list[dict]}
35
    constraints : list[callable], default=[]
36
        A list of constraints, where each constraint is a callable.
37
        The callable returns `True` or `False` dependend on the input parameters.
38
    n_iter : int, default=100
39
        The number of iterations to run the optimizer.
40
    """
41
42
    def __init__(
43
        self,
44
        experiment=None,
45
        random_state=None,
46
        rand_rest_p=0.1,
47
        epsilon=0.01,
48
        distribution="uniform",
49
        n_neighbours=10,
50
        search_space=None,
51
        initialize=None,
52
        constraints=None,
53
        n_iter=100,
54
    ):
55
        self.random_state = random_state
56
        self.rand_rest_p = rand_rest_p
57
        self.epsilon = epsilon
58
        self.distribution = distribution
59
        self.n_neighbours = n_neighbours
60
        self.search_space = search_space
61
        self.initialize = initialize
62
        self.constraints = constraints
63
        self.n_iter = n_iter
64
        self.experiment = experiment
65
66
        super().__init__()
67
68
        if initialize is None:
69
            self._initialize = {"grid": 4, "random": 2, "vertices": 4}
70
        else:
71
            self._initialize = initialize
72
73
    def add_search(self, experiment, **search_config):
74
        """Add a new optimization search process with specified parameters.
75
76
        Parameters
77
        ---------
78
        experiment : BaseExperiment
79
            The experiment to optimize parameters for.
80
        search_space : dict[str, list]
81
            The search space to explore. A dictionary with parameter
82
            names as keys and a numpy array as values.
83
        initialize : dict[str, int], default={"grid": 4, "random": 2, "vertices": 4}
84
            The method to generate initial positions. A dictionary with
85
            the following key literals and the corresponding value type:
86
            {"grid": int, "vertices": int, "random": int, "warm_start": list[dict]}
87
        constraints : list[callable], default=[]
88
            A list of constraints, where each constraint is a callable.
89
            The callable returns `True` or `False` dependend on the input parameters.
90
        n_iter : int, default=100
91
            The number of iterations to run the optimizer.
92
        """
93
        super().add_search(experiment, **search_config)
94
95
    def get_search_config(self):
96
        """Get the search configuration.
97
98
        Returns
99
        -------
100
        dict with str keys
101
            The search configuration dictionary.
102
        """
103
        search_config = super().get_search_config()
104
        search_config["initialize"] = self._initialize
105
106
    def _run(self, experiment, **search_config):
107
        """Run the optimization search process.
108
109
        Parameters
110
        ----------
111
        max_time : float
112
            The maximum time used for the optimization process.
113
        """
114
        n_iter = search_config.pop("n_iter", 100)
115
        max_time = search_config.pop("max_time", None)
116
117
        hcopt = HillClimbingOptimizer(**search_config)
118
119
        hcopt.search(
120
            objective_function=experiment,
121
            n_iter=n_iter,
122
            max_time=max_time,
123
        )
124
        self.best_params_ = hcopt.best_params()
125
126
        return self.best_params_
127