Source code for metaheuristic_designer.encodings.sigmoid_encoding
"""
Encoding that applies a sigmoid function to enable continuous operators on binary problems.
"""
from __future__ import annotations
from typing import Iterable
import scipy as sp
import numpy as np
from ..encoding import Encoding
from ..utils import MatrixLike
[docs]
class SigmoidEncoding(Encoding):
"""
Encoding that maps binary solutions to continuous values via a sigmoid.
The encoding applies :math:`\\sigma(x) = 1 / (1 + e^{-x})` pointwise.
During encoding, the logit function is applied to the probability
parameter (producing real numbers). During decoding, the sigmoid
is applied again. This allows real-valued operators (e.g., Gaussian
mutation) to be used on binary problems.
Parameters
----------
as_probability : bool, optional
If ``True`` (default), each component is returned as a
probability in (0, 1). If ``False``, the probability is
thresholded to produce a hard 0/1 value.
threshold : float, optional
Threshold used when ``as_probability=False``. Must be in
(0, 1). Default is 0.5.
**kwargs
Forwarded to :class:`Encoding`.
"""
def __init__(self, as_probability: bool = True, threshold: float = 0.5, **kwargs):
assert as_probability or 0 < threshold < 1, "The threshold must be a number between 0 and 1"
self.as_probability = as_probability
self.threshold = threshold
super().__init__(decode_as_array=True, **kwargs)
[docs]
def encode(self, solutions: Iterable) -> MatrixLike:
assert np.all((solutions >= 0) & (solutions <= 1)), "To encode solutions with the sigmoid encoding, the values must be in the range (0,1)."
result = sp.special.logit(solutions)
return result
[docs]
def decode(self, population: MatrixLike) -> Iterable:
result = sp.special.expit(population)
if not self.as_probability:
result = (result >= self.threshold).astype(int)
return result