Source code for altbacken.external.temperature

from collections.abc import Iterable, Sequence
from math import log, cos, pi
from typing import Any

from altbacken.core.annealing import AnnealingState


[docs] class PredefinedTemperature: """ Represents a predefined sequence of temperature values. This class allows storing a predefined series of temperatures and provides functionality to iterate over these temperatures in a generator-like fashion. It ensures the sequence is not empty upon instantiation. Attributes: temperature (Sequence[float]): Immutable sequence of predefined temperature values. """
[docs] def __init__(self, temperature: Iterable[float]): self._temperature: Sequence[float] = tuple(temperature) if not self._temperature: raise ValueError("Temperature sequence must not be empty")
[docs] def __call__(self, state: AnnealingState[Any]) -> float: if state.iteration >= len(self._temperature): return 0.0 else: return self._temperature[state.iteration]
[docs] class ExponentialCooling: """ Handles exponential cooling calculations. This class provides functionality for simulating exponential cooling. It calculates decreasing temperature values based on an initial temperature and a specified cooling rate. The `ExponentialCooling` class can be used in optimization problems such as simulated annealing. Attributes: initial_temperature (float): The starting temperature for the cooling process. cooling_rate (float): The rate at which the temperature decreases in each step. It must be a value in the range (0, 1). """
[docs] def __init__(self, initial_temperature: float, cooling_rate: float = 0.9): if initial_temperature <= 0: raise ValueError("Initial temperature must be positive") if cooling_rate <= 0 or cooling_rate >= 1: raise ValueError("Cooling rate must be in (0, 1)") self._initial_temperature = initial_temperature self._cooling_rate = cooling_rate
[docs] def __call__(self, state: AnnealingState[Any]) -> float: return self._initial_temperature * (self._cooling_rate ** state.iteration)
[docs] class LogarithmicCooling: """ Implements a logarithmic cooling schedule generator. The class provides a cooling schedule based on a logarithmic function. It is used commonly in simulated annealing or other optimization algorithms to introduce a gradually decreasing parameter (like temperature). The logarithmic cooling ensures a steady and slow decrease in the temperature value over iterations, making it suitable for problems requiring fine-tuning during optimization. Attributes: initial_temperature (float): The starting temperature value for the cooling schedule. shift (float): A shift factor added to the logarithm denominator to avoid division errors and regulate the cooling rate. """
[docs] def __init__(self, initial_temperature: float, shift: float = 1.1): if shift <= 1: raise ValueError("Shift must be greater than 1") if initial_temperature <= 0: raise ValueError("Initial temperature must be positive") self._initial_temperature: float = initial_temperature self._shift: float = shift
[docs] def __call__(self, state: AnnealingState[Any]) -> float: return self._initial_temperature / log(state.iteration + self._shift)
[docs] class LinearCooling:
[docs] def __init__(self, initial_temperature: float, step: float): if step <= 0: raise ValueError("Step must be positive") if initial_temperature <= 0: raise ValueError("Initial temperature must be positive") self._initial_temperature: float = initial_temperature self._step: float = step
[docs] def __call__(self, state: AnnealingState[Any]) -> float: return max(self._initial_temperature - state.iteration * self._step, 0)
[docs] class AdaptiveCooling: """ Represents a cooling schedule with adaptive adjustments based on the state of the annealing process. This class implements a cooling mechanism for simulated annealing, where the temperature adapts based on the progress and quality of the current state. The temperature either decreases or slightly increases, aiming to balance exploration and exploitation during the optimization process. Attributes: initial_temperature (float): Initial temperature to start the annealing process. cooling (float): Factor to decrement the temperature when the current value is not optimal. heating (float): Factor to increment the temperature slightly to allow further exploration when the current value matches the best value. """
[docs] def __init__(self, initial_temperature: float, cooling: float = 0.9, heating: float = 1.1): if cooling >= 1.0 or cooling <= 0: raise ValueError("Cooling factor must be less than 1 and positive") if heating <= 1.0: raise ValueError("Heating factor must be greater than 1") if initial_temperature <= 0: raise ValueError("Initial temperature must be positive") self._initial_temperature: float = initial_temperature self._cooling: float = cooling self._heating: float = heating
[docs] def __call__(self, state: AnnealingState[Any]) -> float: if state.iteration == 0: return self._initial_temperature return state.temperature * self._heating if state.improvement else state.temperature * self._cooling
[docs] class CosineCooling: """ CosineCooling implements a cosine annealing schedule for temperature adjustment. This class is used to compute a temperature value based on the current iteration of an annealing process. The temperature adjusts according to a cosine curve and decreases gradually with iterations, reaching zero upon exceeding a specified maximum number of iterations. Attributes: initial_temperature (float): The starting temperature value used for the annealing process. max_iterations (int): The maximum allowable iterations for the annealing process, beyond which the temperature is set to zero. """
[docs] def __init__(self, initial_temperature: float, max_iterations: int): """ Initializes the parameters for a simulated annealing process. Args: initial_temperature: Initial temperature for the annealing process, must be a positive floating point value. max_iterations: Maximum number of iterations for the annealing process, must be a positive integer. Raises: ValueError: If `initial_temperature` is not a positive value. ValueError: If `max_iterations` is not a positive value. """ if initial_temperature <= 0: raise ValueError("Initial temperature must be positive") if max_iterations <= 0: raise ValueError("Maximum number of iterations must be positive") self._initial_temperature: float = initial_temperature self._max_iterations: int = max_iterations
[docs] def __call__(self, state: AnnealingState[Any]) -> float: """ Calculates the temperature for the given state based on the annealing schedule. This method computes the temperature using a cosine annealing schedule. The temperature decreases as the number of iterations increases, eventually reaching zero beyond the maximum number of iterations. Args: state (AnnealingState[Any]): The current state of the annealing process. Contains iteration information. Returns: float: The temperature corresponding to the given state. """ if state.iteration > self._max_iterations: return 0.0 else: return 0.5*self._initial_temperature * (1 + cos(state.iteration * pi / self._max_iterations))