Source code for altbacken.external.neighbourhood.numeric

from collections.abc import Sequence, Callable, Iterable
from random import random as builtin_random
from typing import Protocol, Self, cast

from altbacken.core.annealing import RandomNumberGenerator, AnnealingState
from altbacken.core.neighbourhood import no_temperature_scaling, TemperatureScaling
from altbacken.internal.neighbourhood.adaptive import Epsilon, ConstantEpsilon


[docs] class VectorNeighbourhood: """ Defines a class for generating a neighborhood of vectors. The VectorNeighbourhood class generates new vectors by applying a small random perturbation to each component of an input vector. Attributes: epsilon (float): Magnitude of the perturbation applied to the input vector during neighborhood generation. random (RandomNumberGenerator): Random number generator used for creating perturbations. vector_type (Callable[[Iterable[float]], Sequence[float]]): Function used to define the type or structure of the output vector. """
[docs] def __init__( self, epsilon: float | Epsilon[Sequence[float], float] = 0.1, random: RandomNumberGenerator = builtin_random, vector_type: Callable[[Iterable[float]], Sequence[float]] = tuple, temperature_scaling: TemperatureScaling = no_temperature_scaling ): self._epsilon: Epsilon[Sequence[float], float] = cast( Epsilon[Sequence[float], float], ConstantEpsilon(epsilon) if isinstance(epsilon, (int, float)) else epsilon ) self._random: RandomNumberGenerator = random self._vector_type: Callable[[Iterable[float]], Sequence[float]] = vector_type self._temperature_scaling: TemperatureScaling = temperature_scaling
[docs] def __call__(self, vector: AnnealingState[Sequence[float]]) -> Sequence[float]: return self._vector_type( (2.0*self._random()-1) * self._epsilon(vector) * self._temperature_scaling(vector.temperature) + x for x in vector.current_solution )
[docs] class IntegerVectorNeighbourhood: """ Represents a neighborhood function for integer vectors, used in simulated annealing to generate neighboring solutions. This class is designed to provide a way to generate new candidate solutions by perturbing an integer vector. The perturbation is controlled by parameters like epsilon, randomness, and temperature scaling. Attributes: epsilon (int | Epsilon[Sequence[int], int]): The magnitude of the perturbations. If an integer is provided, a constant epsilon is used. Otherwise, a custom Epsilon instance can be specified. random (RandomNumberGenerator): A random number generator used for creating perturbations. vector_type (Callable[[Iterable[int]], Sequence[int]]): A callable that determines the type of vector to be returned, such as tuple or list. temperature_scaling (TemperatureScaling): A function or callable used to scale perturbations based on the current temperature during the annealing process. """
[docs] def __init__( self, epsilon: int | Epsilon[Sequence[int], int] = 1, random: RandomNumberGenerator = builtin_random, vector_type: Callable[[Iterable[int]], Sequence[int]] = tuple, temperature_scaling: TemperatureScaling = no_temperature_scaling ): self._epsilon: Epsilon[Sequence[int], int] = cast( Epsilon[Sequence[int], int], ConstantEpsilon(abs(epsilon)) if isinstance(epsilon, (int, float)) else epsilon ) self._random: RandomNumberGenerator = random self._vector_type: Callable[[Iterable[int]], Sequence[int]] = vector_type self._temperature_scaling: TemperatureScaling = temperature_scaling
[docs] def __call__(self, vector: AnnealingState[Sequence[int]]) -> Sequence[int]: return self._vector_type( (round(2.0*self._random()-1*self._epsilon(vector) * self._temperature_scaling(vector.temperature)) + x) for x in vector.current_solution )
[docs] class SupportsArrayOps(Protocol): shape: tuple[int, ...] def __add__(self, other) -> Self: ...
[docs] class ArrayNeighbourhood[A: SupportsArrayOps]: """ Represents a neighborhood for array-based solutions in optimization algorithms. This class is designed to generate neighboring solutions in an array-based optimization context, such as simulated annealing. It utilizes a specified epsilon value for scaling the neighborhood bounds and applies temperature scaling where applicable. The class is parameterized to work with data types that support array operations. Attributes: epsilon (float | Epsilon[A, float]): Scaling factor for determining the range of the neighborhood bounds. Can either be a constant float or a custom epsilon function. seed (int): Seed for the random number generator to ensure reproducibility of the generated neighbors. temperature_scaling (TemperatureScaling): A function or object used for scaling the neighborhood size based on the current temperature. """
[docs] def __init__( self, epsilon: float | Epsilon[A, float] = 0.1, seed: int = 0, temperature_scaling: TemperatureScaling = no_temperature_scaling ): self._epsilon: Epsilon[A, float] = cast( Epsilon[A, float], ConstantEpsilon(abs(epsilon)) if isinstance(epsilon, (float, int)) else epsilon ) from altbacken.optional.numpy import random self._rng = random.default_rng(seed) self._temperature_scaling = temperature_scaling
[docs] def __call__(self, state: AnnealingState[A]) -> A: array: A = state.current_solution bounds = self._temperature_scaling(state.temperature) * self._epsilon(state) return array + self._rng.uniform(low=-bounds, high=bounds, size=array.shape)