Scipy约束最小化不遵守约束

时间:2018-01-29 13:50:18

标签: python scipy minimize

如果问题看起来简单明了,我道歉。我试图寻找答案,但找不到可以解决我问题的答案。 我有一个非常简单的最小化问题:我需要最大化期望值(在第二阶段,目标函数将变得更复杂):

    def EV(q, P):
       return (-1)*np.sum(100 * q * (2*P - 1))

q是一个12维向量,其元素必须介于0和1之间,显然,q的元素之和为1.所以我继续设置边界和约束:

     cons = {'type': 'eq', 'fun': lambda q: np.sum(q) - 1}
     bds = [(0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1), (0, 1)]
     P = array([ 0.32510069,  0.96284943,  0.33966465,  0.61696874,  0.77368336,
    0.10127222,  0.47836665,  0.87537657,  0.2086234 ,  0.52468426,
    0.31931169,  0.86424427]).

然后我打电话给scipy.optimize.minimize:

    X0 = np.array([0.5,0,0,0,0,0,0,0,0,0,0.4,0])
    qstar = scipy.optimize.minimize(fun = EV, x0 = X0, args = (P), method = 'L-BFGS-B', bounds = bds, constraints = cons).

然而,当我打印解决方案qstar时,我得到以下内容:

    fun: -323.56132559388169
    hess_inv: <12x12 LbfgsInvHessProduct with dtype=float64>
    jac: array([ 34.97985972, -92.56988847,  32.06706651, -23.39374987,
   -54.7366767 ,  79.74555274,   4.32666525, -75.0753145 ,
    58.27532163,  -4.93685093,  36.13766353, -72.84884873])
    message: 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL'
    nfev: 26
    nit: 1
    status: 0
    success: True
    x: array([ 0.,  1.,  0.,  1.,  1.,  0.,  0.,  1.,  0.,  1.,  0.,  1.])

为什么解决方案不满足等式约束?也许是因为这个消息?非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

将解算器方法更改为SLSQP,如注释中所述,仅在SLSQP和COBYLA中支持约束。 SLSQP通过顺序最小二乘二次规划解决了这个问题。

请注意,COBYLA仅支持不等式约束。

fun: -92.56988588438836
jac: array([ 34.97986126, -92.56988621,  32.06707001, -23.39374828,
   -54.7366724 ,  79.74555588,   4.32666969, -75.07531452,
    58.27532005,  -4.93685246,  36.13766193, -72.84885406])
message: 'Optimization terminated successfully.'
nfev: 28
nit: 2
njev: 2
status: 0
success: True
x: array([  2.07808604e-10,   1.00000000e+00,   1.95365391e-10,
     0.00000000e+00,   0.00000000e+00,   4.37596612e-10,
     5.51522994e-11,   0.00000000e+00,   3.28030922e-10,
     8.07265366e-12,   2.14253171e-10,   0.00000000e+00])

给我以下输出。

SteamsBuilder topology = new StreamsBuilder();

KTable<Integer, HashMap<String, Long>> aggregate = topology.stream("input")
  .groupBy((k, v) -> 0 /*map all records to same, arbitrary key*/)
  .aggregate(() -> new HashMap<String, Long>(),
             (k, v, a) -> {
                Long count = a.get(v.get("state"));
                if (count == null) {
                    count = 0L;
                }
                a.put(v.get("state"), ++count);
                return a;
             });