0

I'm on Scipy Optimize, using the fmin_cobyla function. I've struggled to write constraint functions that:

  1. make sure all items sum up to 1
  2. make sure all items >= 0

Does anyone have insight? For fmin_slsqp, for example, I had a function:

def w_constraint(w, v, x0, x1):
    return np.sum(w) - 1

As well as bounds in the function.

But these don't work on cobyla.

2 Answers2

2

Formulate your equality as pair of inequalities. Meaning:

  • x == y becomes:
    • x >= y
    • x <= y = -x >= -y

Of course this may introduce numerical troubles (hurting many kinds of solvers), but i saw this in multiple implementations of COBYLA-interfaces (with equality-constraint support implemented like that).

A comment from the documentation of NLopt:

(The underlying COBYLA code only supports inequality constraints. Equality constraints are automatically transformed into pairs of inequality constraints, which in the case of this algorithm seems not to cause problems.)

sascha
  • 32,238
  • 6
  • 68
  • 110
  • Thank you @sascha; I'm very new to scipy, would you write what I'd have to return in my constraint function? – Guilherme Nazareth de Souza Jan 30 '17 at 02:42
  • @GuilhermeNazarethdeSouza Just check the docs. They are not that bad. Even including examples. (And always remember: "this did not work" is not a helpful error message!) – sascha Jan 30 '17 at 02:42
0

For Scipy.optimize.minimize function, the following should work:

def constraint_func(x_in):
    constraints_list = []
    constraints_list.append({'type': 'ineq', 'fun': lambda x: np.sum(x)-1})
    constraints_list.append({'type': 'ineq', 'fun': lambda x: -np.sum(x)+1})
    for i in range(len(x_in)):
        constraints_list.append({'type': 'ineq', 'fun': lambda x: x[i]})
    return constraints_list

constraints = constraint_func(x0)

res = scipy.optimize.minimize(fun, x0, method='COBYLA', constraints= constraints)