scipy.optimize.minimize() constraints depend on cost function

Viewed 192

I'm running a constrained optimisation with scipy.optimize.minimize(method='COBYLA').

In order to evaluate the cost function, I need to run a relatively expensive computation to compute a dataset from the input variables, and the cost function is one (cheap to compute) property of that dataset. However, two of my constraints are also dependent on that expensive data. So far, the only way I have found to constrain the optimisation is to have each of the constraint functions recompute the same dataset that the cost function already has.

Simplified quasi-code:

# universal cost function evaluator
def criterion_from_x(x, cfun):
    data = expensive_fun(x)
    return(cfun(data))

def costfun(data):
    return(cheap_fun1(data))

def constr1(data):
    return(cheap_fun2(data))

def constr2(data):
    return(cheap_fun3(data))


constraints = [{'type':'ineq', 'fun':criterion_from_x, 'args':(constr1,)},
               {'type':'ineq', 'fun':criterion_from_x, 'args':(constr2,)}

# initial guess
x0 = np.ones((6,))

opt_result = minimize(criterion_from_x, x0, method='COBYLA',
                      args=(costfun,), constraints=constraints)

So I have a universal "evaluate some cost" function which runs the expensive computation, and then evaluates whatever criterion it has been given. But it needs to run three times for every iteration of the optimizer.

I have not managed to find any way to set something up where x is used to generate data, which is then passed to the objective function as well as the constraint functions.

Does something like this exist? I've noticed the callback argument to minimize(), but that is a function which is called after each step. I'd need some kind of preprocessor which is called on x before each step, whose result is then used instead of x. Maybe there's a way to sneak it in somehow? I'd like to avoid writing my own optimizer.

One traditional way to solve this would be to add a penalty function for violated constraints to the main cost function, and run the optimizer without the explicit constraints, but I've tried this before and found that the main cost function can become somewhat chaotic in cases where the constraints are violated, so an optimizer might get stuck in some place which violates the constraints and not find out again.

The code needs to work on machines with Python v2.7.6 to 2.7.13, and scipy 0.13 to 0.17.

0 Answers
Related