optuna
196 строк · 5.2 Кб
1from __future__ import annotations2
3import abc4from typing import Callable5from typing import Union6
7import numpy as np8
9
10class BaseIdenticalTransformation(metaclass=abc.ABCMeta):11@abc.abstractmethod12def __call__(self, y: float) -> float:13raise NotImplementedError14
15
16class BaseBiasTransformation(metaclass=abc.ABCMeta):17@abc.abstractmethod18def __call__(self, y: float) -> float:19raise NotImplementedError20
21
22class BaseShiftTransformation(metaclass=abc.ABCMeta):23@abc.abstractmethod24def __call__(self, y: float) -> float:25raise NotImplementedError26
27
28class BaseReductionTransformation(metaclass=abc.ABCMeta):29@abc.abstractmethod30def __call__(self, y: np.ndarray) -> float:31raise NotImplementedError32
33
34BaseTransformations = Union[35BaseIdenticalTransformation,36BaseBiasTransformation,37BaseShiftTransformation,38BaseReductionTransformation,39]
40
41
42class IdenticalTransformation(BaseIdenticalTransformation):43def __init__(self) -> None:44pass45
46def __call__(self, y: float) -> float:47return y48
49
50class PolynomialBiasTransformation(BaseBiasTransformation):51def __init__(self, alpha: float) -> None:52assert alpha > 0 and alpha != 1.053self._alpha = alpha54
55def __call__(self, y: float) -> float:56return np.power(y, self._alpha)57
58
59class FlatRegionBiasTransformation(BaseBiasTransformation):60def __init__(self, a: float, b: float, c: float) -> None:61assert 0 <= a <= 162assert 0 <= b <= 163assert 0 <= c <= 164assert b < c65assert not (b == 0) or (a == 0 and c != 1)66assert not (c == 1) or (a == 1 and b != 0)67
68self._a = a69self._b = b70self._c = c71
72def __call__(self, y: float) -> float:73a = self._a74b = self._b75c = self._c76return (77a
78+ min(0, np.floor(y - b)) * a * (b - y) / b79- min(0, np.floor(c - y)) * (1.0 - a) * (y - c) / (1.0 - c)80)81
82
83class ParameterDependentBiasTransformation(BaseReductionTransformation):84def __init__(85self,86w: np.ndarray,87input_converter: Callable[[np.ndarray], np.ndarray],88a: float,89b: float,90c: float,91i: int,92) -> None:93assert 0 < a < 194assert 0 < b < c95
96self._w = w97self._input_converter = input_converter98self._a = a99self._b = b100self._c = c101self._i = i102
103def __call__(self, y: np.ndarray) -> float:104w = self._w105a = self._a106b = self._b107c = self._c108i = self._i109
110u = (self._input_converter(y) * w).sum() / w.sum()111v = a - (1.0 - 2 * u) * np.fabs(np.floor(0.5 - u) + a)112return np.power(y[i], b + (c - b) * v)113
114
115class LinearShiftTransformation(BaseShiftTransformation):116def __init__(self, a: float) -> None:117assert 0 < a < 1118
119self._a = a120
121def __call__(self, y: float) -> float:122return np.fabs(y - self._a) / np.fabs(np.floor(self._a - y) + self._a)123
124
125class DeceptiveShiftTransformation(BaseShiftTransformation):126def __init__(self, a: float, b: float, c: float) -> None:127assert 0 < a < 1128assert 0 < b < 1129assert 0 < c < 1130assert a - b > 0131assert a + b < 1132
133self._a = a134self._b = b135self._c = c136
137def __call__(self, y: float) -> float:138a = self._a139b = self._b140c = self._c141
142q1 = np.floor(y - a + b) * (1.0 - c + (a - b) / b)143q2 = np.floor(a + b - y) * (1.0 - c + (1.0 - a - b) / b)144return 1.0 + (np.fabs(y - a) - b) * (q1 / (a - b) + q2 / (1.0 - a - b) + 1.0 / b)145
146
147class MultiModalShiftTransformation(BaseShiftTransformation):148def __init__(self, a: int, b: float, c: float) -> None:149assert a > 0150assert b >= 0151assert (4 * a + 2) * np.pi >= 4 * b152assert 0 < c < 1153
154self._a = a155self._b = b156self._c = c157
158def __call__(self, y: float) -> float:159a = self._a160b = self._b161c = self._c162
163q1 = np.fabs(y - c) / (2 * (np.floor(c - y) + c))164q2 = (4 * a + 2) * np.pi * (0.5 - q1)165return (1.0 + np.cos(q2) + 4 * b * (q1**2)) / (b + 2)166
167
168class WeightedSumReductionTransformation(BaseReductionTransformation):169def __init__(self, w: np.ndarray, input_converter: Callable[[np.ndarray], np.ndarray]) -> None:170assert all(w > 0)171
172self._w = w173self._input_converter = input_converter174
175def __call__(self, y: np.ndarray) -> float:176y = self._input_converter(y)177return (y * self._w).sum() / self._w.sum()178
179
180class NonSeparableReductionTransformation(BaseReductionTransformation):181def __init__(self, a: int, input_converter: Callable[[np.ndarray], np.ndarray]) -> None:182assert a > 0183
184self._a = a185self._input_converter = input_converter186
187def __call__(self, y: np.ndarray) -> float:188a = float(self._a)189y = self._input_converter(y)190n = y.shape[0]191indices = [(j + k + 1) % n for k in np.arange(n) for j in np.arange(n)]192
193q = y.sum() + np.fabs(y[indices].reshape((n, n)) - y)[:, 0 : int(a) - 1].sum()194r = n * np.ceil(a / 2) * (1.0 + 2 * a - 2 * np.ceil(a / 2)) / a195
196return q / r197