Python SciPy:优化问题fmin_cobyla:不遵守一个约束

时间:2013-09-13 08:51:05

标签: python optimization scipy

我有以下优化问题:

目标函数非常简单:给定一个向量SPREAD,我尝试找到向量W以最大化sum(W.SPREAD)

例如,在维度3中,这意味着我尝试最大化w1 x spread1 + w2 x spread2 + w3 x spread3

另外,我有三个约束c1, c2 & c3不在W上,而在POS向量POS = W2POS(W)上。

例如,在维度3中,约束是:

  1. |pos1 + pos2 + pos3| < 5
  2. |pos1| + |pos2| + |pos3| < 500
  3. Max(pos1, pos2, pos3) < 5
  4. 我编写了下面的代码来执行一些优化,但是,约束3没有得到遵守。如何根据我的约束来解决这个问题?

    我写了下面的代码:

    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]
    

    您可以使用此代码来播放一些虚拟数据,这些数据将说明c3未得到遵守:http://pastebin.com/gjbeePgt

1 个答案:

答案 0 :(得分:1)

阅读原始Fortran 77文件 cobyla2.f (可在this包中提供)第38和39行中的文档,声明:

  

C1,C2,...,CM表示最终应该变为非负的约束函数,至少达到RHOEND的精度

如果我正确解释fmin_cobyla scipy API文档,默认情况下RHOEND设置为 1.0E-4

如果观察到的约束违规确实小于RHOEND但仍然大得令人无法接受,那么问题的一个简单解决方案就是将RHOEND的值纳入约束公式中,即

C[i] + RHOEND >= 0

在这种特殊情况下, 看起来像约束违规大于RHOEND,这已由Pauli Virtanen构建的new test case in the scipy repository完全说明,并且对应上述问题。

为避免在此特定情况下违反约束,解决方案似乎是在RHOBEG上使用较小的值启动优化,例如 0.01