GpyOpt ignores constraints. What is the correct way to specify them?

1k views Asked by At

I want to run a constrained optimization in GpyOpt. Say, I want to minimize

where

s.t. at least one is non-zero and, and not more than 3 can be equal to 1. So I specify constraints:

Based on the reference manual here, it looks like we can specify constraints using numpy function. And here is suggested that we can specify constraints in the call to BayesianOptimization. So I express this in GpyOpt using the following code

import numpy as np
import GPyOpt
from GPyOpt.methods import BayesianOptimization

seed = 6830
np.random.seed(seed)

def f(x):
    print(np.sum(x[:]), end=" ") # check if constraints are satisfied
    z = np.sum(x)
    return z**2

bounds = [{"name": "x", "type" : "discrete", 
           "domain" : (0, 1), "dimensionality": 10}]

constraints = [{'name' : 'more_than_0','constraint' : '-np.sum(x[:]) + 0.1'},
               {'name' : 'less_than_3','constraint' : 'np.sum(x[:]) - 3'}]

bopt = BayesianOptimization(f, domain=bounds, constraints=constraints)
bopt.run_optimization(max_iter=10)

However, it looks like GpyOpt is ignoring these constraints because I get the following output in the console:

6.0 1.0 5.0 7.0 3.0 2.0 2.0 0.0 1.0 3.0 1.0 1.0 1.0 0.0 2.0 

which contains both values above 3 and a 0.

If I write out np.sum(x[:]) explicitly as x[:, 0] + x[:, 1] + ... the behaviour does not change.

If I specify continuous domain, constraints are still violated.

What is the correct way to pass constraints, such that they are not ignored?

I am using GpyOpt version 1.2.1.

UPDATE: np.sum(x, 1) instead of np.sum(x[:]) does not solve the issue.

I am using Python 3.6.3 with numpy 1.14.2 and GPyOpt 1.2.1 installed through pip.

1

There are 1 answers

3
Andrei On BEST ANSWER

I am not sure you are summing up the x's right. The constraint expression is supposed to work over whole X and output an array of values per data point, which are then each checked against the constraint.

When I change the summing in both expressions to:

np.sum(x, axis=1)

and leave your code otherwise completely intact, the output is:

1.0 2.0 1.0 2.0 2.0 2 2 2 2 1 2 2 1 2 1

No violations.