Scipy differential evolution - non-continuous bounds

135 views Asked by At

I am trying to setup a differential_evolution algorithm. I have approximately 15 variables, each with its own bounds (let's suppose they all share the same bounds (150,250). I have successfully accomplished to do so.

Now, I would like to add the possibility for any parameter to be set to 0 (or any small number would be fine).

Is there any way that I could set the bounds for my parameters to be (0,0.1) U (150, 250)? Can this be achieved through some kind of constraint?

1

There are 1 answers

3
Reinderien On

Here's a wild guess. It's enough to configure differential_evolution for the kind of constraint you want. It isn't enough to run a meaningful optimization, but there's no sense in tuning for an objective function that you haven't provided.

import numpy as np
from scipy.optimize import differential_evolution, LinearConstraint


def objective(x: np.ndarray) -> float:
    a, b, a_selected, b_selected = x
    return a*b


constraint = LinearConstraint(
    A=(
        (1, 0, -150,    0),  # a >= 150s
        (1, 0, -250,    0),  # a <= 250s
        (0, 1,    0, -150),  # b >= 150t
        (0, 1,    0, -250),  # b <= 250t
    ),
    lb=(0, -np.inf, 0, -np.inf),
    ub=(+np.inf, 0, +np.inf, 0),
)

result = differential_evolution(
    func=objective,
    bounds=(
        (0, 250),
        (0, 250),
        (0, 1),
        (0, 1),
    ),
    integrality=(False, False, True, True),
    constraints=constraint,
)
assert result.success, result.message
a, b, a_selected, b_selected = result.x
print(f'a = {np.round(a, 3)}, selected: {a_selected}')
print(f'b = {np.round(b, 3)}, selected: {b_selected}')
print(f'f = {np.round(result.fun, 3)}')