Lorifan
Lorifan

Reputation: 21

Python SciPy: optimization issue fmin_cobyla : one constraint is not respected

I have the below optimisation problem:

The objective function is quite simple: given a vector SPREAD, I try to find the vector W to maximize sum(W.SPREAD).

As an example, in dimension 3, this mean I try to maximize w1 x spread1 + w2 x spread2 + w3 x spread3.

Plus, I have three constraints c1, c2 & c3 not on W, but on a POS vector where POS = W2POS(W).

As an example, in dimension 3, contraints are:

  1. |pos1 + pos2 + pos3| < 5
  2. |pos1| + |pos2| + |pos3| < 500
  3. Max(pos1, pos2, pos3) < 5

I wrote the below code which perform some optimization, however, constraints 3 is not respected. How can I solve this problem respecting my constraints?

I wrote the below code:

from scipy.optimize import fmin_cobyla
import numpy as np
import pandas as pd

def W2POS(W, PRICE, BETA):
    POS = (PRICE * BETA).T.dot(W)
    return POS

def objective(W, SPREAD, sign = 1):
    er = sum((W * SPREAD.T).sum())
    return sign * er

def c1(x, *args):
    """ abs(sum(c)) < 500    """
    POS = W2POS(x,args[0], args[1]) 
    return POS.apply(abs).sum()

def c2(x, *args):
    """ abs(sum()) < 5    """
    POS = W2POS(x,args[0], args[1]) 
    return 5. - abs(POS.sum())

def c3(x, *args):
    """ abs(max(pos)) < 5   """
    POS = W2POS(x,args[0], args[1]) 
    return 5. - POS.apply(abs).max()

# optim
W0 = np.zeros(shape=(len(BETA), 1))
sign = -1
W = fmin_cobyla(objective, W0, cons = [c1, c2, c3], args=(SPREAD,sign), 
                consargs=(PRICE, BETA), maxfun=100, rhobeg = 0.02).T
print 'Solution:', W
args = [PRICE, BETA]
pos = W2POS(W.T,args[0], args[1]) 
print 'c1 < 5:', abs(pos.sum())[0]
print 'c2 < 500:', pos.apply(abs).sum()[0]
print 'c3 < 5:', pos.apply(abs).apply(max)[0]

You can play with some dummy data that will illustrate c3 being not respected with this code : http://pastebin.com/gjbeePgt

Upvotes: 2

Views: 1772

Answers (1)

Anders Gustafsson
Anders Gustafsson

Reputation: 15981

Reading the documentation in the original Fortran 77 file cobyla2.f (available in this package), lines 38 and 39, it is stated:

C1,C2,...,CM denote the constraint functions that should become nonnegative eventually, at least to the precision of RHOEND

If I interpret the scipy API documentation for fmin_cobyla correctly, RHOEND is by default set to 1.0E-4.

If the observed constraint violations are indeed less than RHOEND but still unacceptably large, a simple solution to the issue would be to incorporate the value of RHOEND in the constraint formulations, i.e.

C[i] + RHOEND >= 0

In this particular case, it does appear like the constraint violation is larger than RHOEND, which has been thoroughly illustrated by a new test case in the scipy repository, constructed by Pauli Virtanen, and corresponding to the above question.

To avoid constraint violation in this particular case, the solution appears to be to start the optimization with a smaller value on RHOBEG, for example 0.01.

Upvotes: 1

Related Questions