diff --git a/bitten/bitten.py b/bitten/bitten.py index 37c5e38..9210824 100644 --- a/bitten/bitten.py +++ b/bitten/bitten.py @@ -171,6 +171,28 @@ def _penalize3(constraints, *x, tol=1e-5, scale=1e10, growth=3.0): return scale * (penalty - nominal + 1.0) +def _penalize4(constraints, *x, tol=1e-5, scale=1e9): + # updated from upstream (v2022.23) + # NOTE: i've reduced `scale` by a factor of ten + # out of concern for numeric precision. + # also, i've removed the growth keyword, since it very likely + # needs to coincide with the order of the polynomial (always 3). + penalties = _flatten(cons(*x) for cons in constraints) + n_con = len(penalties) + growth = 3.0 ** (1.0 / n_con) # "ps" + increment = n_con**-0.5 # "pnsi" + # coeff = increment**3.0 # "pnm" + penalty, nominal = 0.0, 0.0 # "pns", "pnsm" + for p in penalties: + p = max(p - tol, 0.0) + v = p # * coeff # 2022.25 drops the coeff + v2 = v * v + poly = v + v2 + v * v2 + penalty = penalty * growth + increment + poly + nominal = nominal * growth + increment + return scale * (penalty - nominal + 1.0) + + def penalize(x, constraints, tol=1e-5, *, scale=1e10, growth=4.0): # DEPRECATED return _penalize(constraints, x, tol=tol, scale=scale, growth=growth) @@ -294,9 +316,10 @@ class Constrain(Objective): @version.setter def version(self, version): - assert 1 <= version <= 3, version + penalizers = [_penalize, _penalize2, _penalize3, _penalize4] + assert 1 <= version <= len(penalizers), version self._version = version - 1 - self._penalize = [_penalize, _penalize2, _penalize3][self._version] + self._penalize = penalizers[self._version] def penalize(self, *args): return self._penalize(self.constraints, *args, tol=self.tol)