You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用mystic求解简单约束优化问题出现次优解且违反约束

约束优化求解异常问题排查

我正在处理一个约束优化问题,求解结果和最优解偏差很大。为方便分析,我简化了目标函数,经解析可知:inv2的系数(1.4)高于inv1(1.1),且日期系数为正,所以应该在月末日期优先最大化inv2的资源分配。但求解器给出的结果完全不符合这个逻辑,还出现了总资源未耗尽(违反100000总额约束)的情况。我怀疑代码里有关键小错误,想先排查这些问题,再去研究差分进化算法本身。

问题代码

import pandas
from datetime import timedelta
from datetime import datetime
from dateutil.tz import gettz
import mystic
from mystic.symbolic import simplify
from mystic.symbolic import generate_constraint, generate_solvers
from mystic.monitors import VerboseMonitor
from mystic.symbolic import symbolic_bounds


horizon = 30
nowianatimezone = datetime.now(tz=gettz(name='Europe/Stockholm'))
datesbetweendates = pandas.date_range(start=nowianatimezone,
                                      end=nowianatimezone + timedelta(days=horizon),
                                      freq='d')
daysforcalculation = datesbetweendates.day.tolist()

def objectiveforoneday(inv1, inv2, day):
    return 1.1 * inv1 + 1.4 * inv2 + 10 * day
            
def objective(x):
    tbret = 0
    for idx, day in enumerate(daysforcalculation):
        inv1 = x[idx * 2]
        inv2 = x[(idx * 2) + 1]
        tbret += objectiveforoneday(inv1=inv1,
                                    inv2=inv2,
                                    day=day)
    return tbret

constraints = '''
x0 >= 250.0
x1 >= 100.0
x2 >= 250.0
x3 >= 100.0
x4 >= 250.0
x5 >= 100.0
x6 >= 250.0
x7 >= 100.0
x8 >= 250.0
x9 >= 100.0
x10 >= 250.0
x11 >= 100.0
x12 >= 250.0
x13 >= 100.0
x14 >= 250.0
x15 >= 100.0
x16 >= 250.0
x17 >= 100.0
x18 >= 250.0
x19 >= 100.0
x20 >= 250.0
x21 >= 100.0
x22 >= 250.0
x23 >= 100.0
x24 >= 250.0
x25 >= 100.0
x26 >= 250.0
x27 >= 100.0
x28 >= 250.0
x29 >= 100.0
x30 >= 250.0
x31 >= 100.0
x32 >= 250.0
x33 >= 100.0
x34 >= 250.0
x35 >= 100.0
x36 >= 250.0
x37 >= 100.0
x38 >= 250.0
x39 >= 100.0
x40 >= 250.0
x41 >= 100.0
x42 >= 250.0
x43 >= 100.0
x44 >= 250.0
x45 >= 100.0
x46 >= 250.0
x47 >= 100.0
x48 >= 250.0
x49 >= 100.0
x50 >= 250.0
x51 >= 100.0
x52 >= 250.0
x53 >= 100.0
x54 >= 250.0
x55 >= 100.0
x56 >= 250.0
x57 >= 100.0
x58 >= 250.0
x59 >= 100.0
x60 >= 250.0
x61 >= 100.0
x0 <= 16666.666666666668
x1 <= 16666.666666666668
x2 <= 16666.666666666668
x3 <= 16666.666666666668
x4 <= 16666.666666666668
x5 <= 16666.666666666668
x6 <= 16666.666666666668
x7 <= 16666.666666666668
x8 <= 16666.666666666668
x9 <= 16666.666666666668
x10 <= 16666.666666666668
x11 <= 16666.666666666668
x12 <= 16666.666666666668
x13 <= 16666.666666666668
x14 <= 16666.666666666668
x15 <= 16666.666666666668
x16 <= 16666.666666666668
x17 <= 16666.666666666668
x18 <= 16666.666666666668
x19 <= 16666.666666666668
x20 <= 16666.666666666668
x21 <= 16666.666666666668
x22 <= 16666.666666666668
x23 <= 16666.666666666668
x24 <= 16666.666666666668
x25 <= 16666.666666666668
x26 <= 16666.666666666668
x27 <= 16666.666666666668
x28 <= 16666.666666666668
x29 <= 16666.666666666668
x30 <= 16666.666666666668
x31 <= 16666.666666666668
x32 <= 16666.666666666668
x33 <= 16666.666666666668
x34 <= 16666.666666666668
x35 <= 16666.666666666668
x36 <= 16666.666666666668
x37 <= 16666.666666666668
x38 <= 16666.666666666668
x39 <= 16666.666666666668
x40 <= 16666.666666666668
x41 <= 16666.666666666668
x42 <= 16666.666666666668
x43 <= 16666.666666666668
x44 <= 16666.666666666668
x45 <= 16666.666666666668
x46 <= 16666.666666666668
x47 <= 16666.666666666668
x48 <= 16666.666666666668
x49 <= 16666.666666666668
x50 <= 16666.666666666668
x51 <= 16666.666666666668
x52 <= 16666.666666666668
x53 <= 16666.666666666668
x54 <= 16666.666666666668
x55 <= 16666.666666666668
x56 <= 16666.666666666668
x57 <= 16666.666666666668
x58 <= 16666.666666666668
x59 <= 16666.666666666668
x60 <= 16666.666666666668
x61 <= 16666.666666666668
x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19 + x20 + x21 + x22 + x23 + x24 + x25 + x26 + x27 + x28 + x29 + x30 + x31 + x32 + x33 + x34 + x35 + x36 + x37 + x38 + x39 + x40 + x41 + x42 + x43 + x44 + x45 + x46 + x47 + x48 + x49 + x50 + x51 + x52 + x53 + x54 + x55 + x56 + x57 + x58 + x59 + x60 + x61 == 100000'''

constraintsimplified = simplify(constraints,
                                all=True)

generatedconstraints = generate_constraint(generate_solvers(constraintsimplified))

initvals = [0.0 for _ in range(len(daysforcalculation) * 2)]
stepmon=VerboseMonitor(10)
import numpy as np
cost = lambda x: -objective(x)
optimum = mystic.solvers.diffev2(cost,
                                 x0=initvals,
                                 constraints=generatedconstraints,
                                 # bounds=bounds,
                                 #full_output=True,
                                 #stepmon=stepmon,
                                 #disp=True,
                                 npop=100,
                                 maxiter=10000)

optimalvalueslst = optimum[0]

# 求解结果
array([16666.66666667,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ,   250.        ,   100.        ,
         250.        ,   100.        ])

排查出的核心问题

  • 约束执行强度不足:
    mystic的generate_constraint默认生成软约束,不会严格强制执行等式约束(总额=100000),导致求解器可以轻易违反该约束。需要改用硬约束模式,或者在生成约束时指定handler="hard",确保约束被严格满足。

  • 单个变量上限设置错误:
    约束中给每个inv1/inv2都设置了16666.666的上限,这个数值完全不符合逻辑——总资源才100000,却允许单个变量占用近1/6的总资源,且62个变量的上限总和远超100000,这会干扰求解器的资源分配逻辑,应该删除这些无意义的单个变量上限。

  • 初始值设置不合理:
    初始值全设为0,与约束要求的inv1>=250、inv2>=100冲突,差分进化算法需要从满足约束的初始种群开始迭代,否则可能陷入局部最优,无法找到正确的分配方案。

  • 求解器参数未配置调试信息:
    注释掉了full_output=True和disp=True,无法查看求解过程中的约束满足情况、迭代收敛状态,难以定位问题。打开这些参数可以帮助判断是约束未生效还是算法未收敛。

内容的提问来源于stack exchange,提问作者chrisrichardsson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 22:15:41