Source code for metaheuristic_designer.constraint_handlers.linear_bound_penalty_constraint
from __future__ import annotations
import numpy as np
from ..constraint_handler import PenalizeConstraint
from ..utils import ScalarLike, VectorLike, MatrixLike
[docs]
class LinearBoundPenaltyConstraint(PenalizeConstraint):
"""
Encodes a bound constraint by adding a penalty proportional to the distance of the
solution's distance to the bounds.
Parameters
----------
dimension: int
size of the input vector (decoded).
alpha: float, optional
factor to multiply to the penalty before being applied.
lower_bound: float | ndarray, optional
lower limit of the bounds.
upper_bound: float | ndarray, optional
upper limit of the bounds.
"""
def __init__(
self, dimension, alpha: ScalarLike = 1, lower_bound: ScalarLike | VectorLike = -100, upper_bound: ScalarLike | VectorLike = 100, **kwargs
):
self.dimension = dimension
self.alpha = alpha
if np.ndim(upper_bound) < 1:
upper_bound = np.repeat(upper_bound, dimension)
self.upper_bound = upper_bound
if np.ndim(lower_bound) < 1:
lower_bound = np.repeat(lower_bound, dimension)
self.lower_bound = lower_bound
self.range_lim = self.upper_bound - self.lower_bound
super().__init__(**kwargs)
[docs]
def penalty(self, population_matrix: MatrixLike) -> VectorLike:
if np.all(self.upper_bound == self.lower_bound):
if self.upper_bound.ndim == 0:
return np.full_like(population_matrix, self.upper_bound)
return np.tile(self.upper_bound, (population_matrix.shape[0], 1))
low_bound_diff = np.maximum(self.lower_bound - population_matrix, 0)
up_bound_diff = np.maximum(population_matrix - self.upper_bound, 0)
total_violation = np.sum(low_bound_diff + up_bound_diff, axis=1)
return self.alpha * total_violation