Source code for niapy.algorithms.other.hc

# encoding=utf8
import logging

from niapy.algorithms.algorithm import Algorithm

logging.basicConfig()
logger = logging.getLogger('niapy.algorithms.other')
logger.setLevel('INFO')

__all__ = ['HillClimbAlgorithm']


def neighborhood(x, delta, task, rng):
    r"""Get neighbours of point.

    Args:
        x (numpy.ndarray): Point.
        delta (float): Standard deviation.
        task (Task): Optimization task.
        rng (numpy.random.Generator): Random generator.

    Returns:
        Tuple[numpy.ndarray, float]:
            1. New solution.
            2. New solutions function/fitness value.

    """
    new_x = x + rng.normal(0, delta, task.dimension)
    new_x = task.repair(new_x, rng)
    new_x_fitness = task.eval(new_x)
    return new_x, new_x_fitness


[docs]class HillClimbAlgorithm(Algorithm): r"""Implementation of iterative hill climbing algorithm. Algorithm: Hill Climbing Algorithm Date: 2018 Authors: Jan Popič License: MIT Reference URL: Reference paper: See Also: * :class:`niapy.algorithms.Algorithm` Attributes: delta (float): Change for searching in neighborhood. neighborhood_function (Callable[numpy.ndarray, float, Task], Tuple[numpy.ndarray, float]]): Function for getting neighbours. """ Name = ['HillClimbAlgorithm', 'HC']
[docs] @staticmethod def info(): r"""Get basic information about the algorithm. Returns: str: Basic information. See Also: :func:`niapy.algorithms.algorithm.Algorithm.info` """ return r"""TODO"""
[docs] def __init__(self, delta=0.5, neighborhood_function=neighborhood, *args, **kwargs): """Initialize HillClimbAlgorithm. Args: * delta (Optional[float]): Change for searching in neighborhood. * neighborhood_function (Optional[Callable[numpy.ndarray, float, Task], Tuple[numpy.ndarray, float]]]): Function for getting neighbours. """ kwargs.pop('population_size', None) super().__init__(1, *args, **kwargs) self.delta = delta self.neighborhood_function = neighborhood_function
[docs] def set_parameters(self, delta=0.5, neighborhood_function=neighborhood, **kwargs): r"""Set the algorithm parameters/arguments. Args: * delta (Optional[float]): Change for searching in neighborhood. * neighborhood_function (Optional[Callable[numpy.ndarray, float, Task], Tuple[numpy.ndarray, float]]]): Function for getting neighbours. """ kwargs.pop('population_size', None) super().set_parameters(population_size=1, **kwargs) self.delta = delta self.neighborhood_function = neighborhood_function
[docs] def get_parameters(self): d = super().get_parameters() d.pop('population_size', None) d.update({ 'delta': self.delta, 'neighborhood_function': self.neighborhood_function }) return d
[docs] def init_population(self, task): r"""Initialize stating point. Args: task (Task): Optimization task. Returns: Tuple[numpy.ndarray, float, Dict[str, Any]]: 1. New individual. 2. New individual function/fitness value. 3. Additional arguments. """ x = task.lower + self.random(task.dimension) * task.range return x, task.eval(x), {}
[docs] def run_iteration(self, task, x, fx, best_x, best_fitness, **params): r"""Core function of HillClimbAlgorithm algorithm. Args: task (Task): Optimization task. x (numpy.ndarray): Current solution. fx (float): Current solutions fitness/function value. best_x (numpy.ndarray): Global best solution. best_fitness (float): Global best solutions function/fitness value. **params (Dict[str, Any]): Additional arguments. Returns: Tuple[numpy.ndarray, float, numpy.ndarray, float, Dict[str, Any]]: 1. New solution. 2. New solutions function/fitness value. 3. Additional arguments. """ lo, xn = False, task.lower + task.range * self.random(task.dimension) xn_f = task.eval(xn) while not lo: yn, yn_f = self.neighborhood_function(x, self.delta, task, rng=self.rng) if yn_f < xn_f: xn, xn_f = yn, yn_f else: lo = True or task.stopping_condition() best_x, best_fitness = self.get_best(xn, xn_f, best_x, best_fitness) return xn, xn_f, best_x, best_fitness, {}