1. 为什么约束优化是进化计算最难啃的骨头
做进化算法这些年,我最大的感受是:真正让一个算法从“玩具”变成“工程可用”的关键,往往不在交叉变异算子,而在约束处理。很多人入门时盯着种群规模、编码方式、自适应参数这些显眼的旋钮,但实际跑实验时真正让人崩溃的,几乎总是那些不起眼的约束细节。这篇《软件学报》2023年发表的综述《面向复杂约束优化问题的进化算法综述》,正好把这一整块内容从算法脉络到前沿场景系统梳理了一遍。我读完之后最大的收获不是记住了哪篇文献提出了哪个方法,而是对整个约束优化领域的技术地图有了一个相对完整的坐标,也对自己之前踩过的一些坑有了更清楚的归因。写这篇阅读笔记,就是为了把这套地图连同我自己在实践中的体感一起整理出来,给同样在做进化算法、约束优化方向的人一个可参考的索引。
先说这篇综述的定位。它把对象定义成“复杂约束优化问题”,这个“复杂”我理解至少包含三层含义:一是约束本身复杂,等式与不等式混合、约束之间存在耦合或冲突;二是问题规模复杂,决策变量维数高、约束数量多;三是评价代价复杂,每次目标与约束计算都可能要调用昂贵的数值仿真。这三层决定了后面所有技术设计的出发点。论文的叙述大致沿着“约束处理技术谱系→复杂场景适配→基准与评估→开放问题”展开,前半部分对几十年来的约束处理技术做了系统梳理,后半部分把目光投向代理模型、大规模、动态、多约束这些更贴近实际需求的场景。相比早期一些综述重点放在罚函数与可行性准则的对比上,这篇的材料综合度高不少,尤其是对近些年多目标转化类和混合方法的讨论,信息量相当可观。
不过我得先给一个个人总判断,方便你带着结论去读后面的细节:约束优化里没有银弹。综述中梳理的多种方法在标准测试集上各有胜负,差异往往体现在问题结构上,而不是方法本身的高低。论文里有一句反复出现的意思,我印象很深——约束处理的关键在于协调可行性与目标函数之间的平衡,而这个平衡本身是动态的、随搜索阶段变化的。所以与其执着于寻找一个万能参数,不如关注算法有没有能力自适应地调节惩罚强度或可行偏向。这个结论听起来不太新鲜,但正因为“不新鲜”,很多人反而低估了它的实操价值。
2. 约束处理技术的谱系:论文怎么梳理这几十年的发展
2.1 罚函数法:最直觉但最考验调参功力
罚函数法的思路近乎直觉:把约束违反量乘上一个系数加到目标函数里,把有约束问题变成无约束问题。早期教科书几乎都从它讲起,综述当然也没跳过。但这次读下来,我比较注意的是论文对罚函数法“结构性缺陷”的剖析:罚系数太小,不可行解可以大摇大摆地存活;罚系数太大,可行域之外的搜索空间几乎没有有效梯度,种群很容易在少数可行解周围早熟。
我自己在实践里踩过一个典型坑:罚系数的尺度敏感。比如一个目标值在1000量级、约束违反量只有0.01量级的混合问题,罚系数设为1时,约束基本形同虚设;罚系数调到10000时,一旦可行域占比极小,种群连进化的方向都找不到。论文里提到的自适应罚函数、动态调节罚系数,本质上是想绕开“罚系数是常数”这个死结。但现实很骨感——自适应机制往往又引入新参数,真正既鲁棒又少参数的自适应策略,直到现在也还是研究热点。所以我的体感是:罚函数法适合做基线,适合早期快速验证想法,但不适合作为最后报结果的主力算法。
2.2 可行性优先与随机排序
可行性优先准则的经典来源是Deb提出的三条比较规则:可行解总是优于不可行解;两个可行解按目标函数值比较优劣;两个不可行解按约束违反度比较优劣。这套规则实现起来非常朴素,却有一种奇特的实用性,直到今天仍是很多约束处理算法默认的基线。不过它的弊端也清楚:过于偏向可行域会丧失对不可行区域的探索。尤其是可行域极窄、初始化种群很难落在可行域内的问题,可行性优先会让整个搜索陷入“全不可行→按违反度排序→慢慢爬向可行域”的长链条里,前期进度慢得让人怀疑人生。
随机排序就是针对这个痛点提的。它的核心是把约束比较以一定概率掺进选择过程:对个体做类似冒泡的排序时,每一次相邻比较都有一定概率只依据目标函数,暂时不看约束信息。论文对随机排序的评价是“在保持可行偏向的同时保留不可行区域的搜索路径”,这个评价我完全同意。实际使用中,随机排序的概率参数PF——也就是无约束比较发生的概率——取0.45左右比较稳。这个值很有意思:太高就退化成纯目标优化,太低又逼近可行性优先。综述里也把PF当作随机排序最主要的灵敏度来源,这一点和我实验中的观察是一致的。
2.3 ε约束方法
ε约束方法的策略是给约束违反度设一个逐渐缩减的阈值ε:搜索初期ε较大,约束违反较多也能作为候选保留;随着迭代推进ε不断下降,最后逼近0,算法逐渐落到严格可行区域。这个思路和模拟退火有些神似,本质上是一个“从宽到严”的可行域逼近过程。综述对ε约束方法的梳理比较完整,也直接指出ε的下降速率对结果影响非常大——过快会破坏探索,过慢则浪费计算预算。
工程上有一种做法是把ε和种群当前的约束违反度分布挂钩,比如取种群约束违反度中位数的一定比例作为初值,再按代数线性衰减到0。这种设计在CEC系列测试集上表现比较稳定,鲁棒性比固定罚系数强不少。我自己用下来的经验是:ε初始值不能设成0,否则等价于可行性优先;也不能设得让所有不可行解都随意通过,否则前期会退化成无约束优化。这个“度”比罚系数还难把握一点,但优点是自适应版本不容易出现数量级爆炸,代码实现也直观,适合作为复杂约束优化的默认基线之一。
2.4 多目标转化与混合方法
多目标转化是近几年约束处理最活跃的方向之一。核心思想很聪明:把约束违反度拆成或聚合成一个或多个附加目标,把单目标约束优化问题转成多目标优化问题。常见做法包括“目标+约束违反度”的双目标形式,以及把每个约束看作独立目标的“约束+目标”多目标形式。转化之后,搜索变成在多目标空间里同时压低目标与约束违反度,多目标进化算法的那套非支配排序、分解策略就都能用上了。综述里对这类方法与Pareto支配、MOEA/D变体结合的讨论,我认为是全文比较出彩的部分。
混合方法则是把已有的技术按不同阶段或不同个体组合起来,形成互补。比如前期用可行性优先快速定位可行域附近,后期用随机排序保持多样性;或者罚函数与ε约束组合使用,让罚系数不那么敏感。论文里用“混合方法的效果往往优于单一技术”总结了这些实践。我读到这里时其实有点感慨——这个领域的进步方式不是“旧方法被淘汰”,而是“旧方法在新框架里被重新组合”。下表是我在阅读笔记里整理的快速对照,不一定完整,但够日常参考。
| 约束处理技术 | 核心思想 | 主要优点 | 主要瓶颈 |
|---|---|---|---|
| 罚函数法 | 目标加上罚系数乘以违反度 | 实现简单,理解直观 | 罚系数尺度敏感,易早熟 |
| 可行性优先 | 可行解优先,不可行按违反度排序 | 稳定,适合做基线 | 牺牲不可行域探索 |
| 随机排序 | 概率化开关约束比较 | 保留不可行搜索路径 | PF参数需要调节 |
| ε约束 | 动态放宽再收紧违反阈值 | 渐进逼近可行域,鲁棒性好 | ε下降速率敏感 |
| 多目标转化 | 将违反度作为额外目标 | 直接复用多目标算法生态 | 计算开销上升 |
| 混合方法 | 多技术按阶段或个体组合 | 兼顾多样性与收敛 | 结构设计复杂度高 |
3. 读到最需要警惕的几个技术细节
3.1 等式约束的容忍度,别想当然
很多刚开始接触约束优化的人会以为等式约束只是“取可行解恰好满足等式”的简单情形,实际远没有那么简单。连续优化中,等式约束 h_j(x)=0 几乎不可能被有限精度算法精确满足,因此几乎所有标准测试集都采用一个容忍度δ,把等式约束改写成 |h_j(x)| ≤ δ 再处理。但δ怎么取,直接影响搜索形态:δ过大,约束形同虚设;δ过小,可行域几乎不存在,等于人为制造了一个无解题。
论文在说明这类问题时,把等式约束描述成“把可行域压缩到一个低维流形上”,算法相当于要在这个流形附近搜索。这里我想补充一点实操体会:不少工作在搜索早期给δ一个稍大的值,让种群先在流形附近找到“着陆点”,后期再把δ收紧以保证精度。这个操作能显著提高等式约束问题的成功率,但前提是衰减策略要设计得平滑。如果前期搜到的点离流形太远,后期收紧δ后种群可能整体被判为不可行,之前积累的信息几乎全部作废。这个问题在综述里属于“预处理”层面的细节,但在我的经验里,它对实验成败的影响往往比算法主体还大。
3.2 约束违反度归一化,容易被忽视的工程细节
多约束优化的一个经典困境是:不同约束的量纲和数值范围相差巨大。比如一个约束是 x₁ ≤ 10,另一个约束是 x₂² + x₂ ≤ 0.001,如果不做归一化,总约束违反度几乎等于数值尺度最大的那一两项的贡献,其余约束等于彻底失效。这个问题在论文讨论约束违反度计算时被明确点了出来。我读的时候特别有共鸣,因为这是我在实际项目中遇到过的最隐蔽的问题——测试集上完全暴露不出来,一上真实工程问题就翻车。
处理办法不外乎两类:一是按单个约束在初始种群上的违反度范围做归一化;二是先对每个约束单独计算亏欠程度,再用平均或加权方式聚合。综述把这些细节放在问题预处理的位置,看起来轻描淡写,实际价值极高。我的建议是,任何准备把进化算法用于多约束工程问题的人,第一件事应该是统计每个约束违反量在初始种群中的分布,而不是埋头设计算子。这一步不做,后面所有约束处理技术都可能在“假约束”上做无用功。
3.3 不可行个体的利用,牵一发动全身
约束处理并不只是“怎么惩罚违反”,更关键的是“不可行解还有没有搜索价值”。可行域外的不可行解携带贴近边界的梯度信息、可行域的轮廓信息,不同不可行解之间甚至能连成一条通往可行区的路径。论文对这一点的论述比较连续:过度惩罚不可行解,等价于把种群按在可行域的小块里,多样性迅速下降;完全不惩罚,又会让算法只顾目标函数而彻底忽视约束。
实际操作中,常用的办法是控制种群中不可行解的比例,比如初期让不可行比例保持在40%上下,之后再用可行性优先或ε约束逐渐收口。这个问题和很多方向都交织在一起:多样性维护要管、约束处理要管、重组算子产生的后代分布也要管。所以我认为“约束处理”其实是一个系统性问题,论文后续讨论的自适应机制、混合结构,本质上都是围绕这个系统性在展开。读到这里我也更加理解,为什么单独调一个罚系数或单独改一个选择策略很难带来本质提升——因为约束优化从根上就不是一个局部问题。
4. 复杂约束场景下研究进展的图谱
4.1 大规模和高维约束优化
把“大规模”和“约束优化”放在一起,难度会叠加式上升。这里的大规模通常指决策变量维数达到几百上千维,同时约束数量也可能同步增长。传统约束处理技术在低维问题上表现良好,但到了高维空间会遇到两个麻烦:一是不可行区域比例急剧上升,约束处理容易让搜索停滞,种群长时间无法产生可行解;二是大量约束违反度计算带来显著开销,很多约束之间还有信息冗余。
综述把这类问题与大规模进化优化的一般思路结合讨论,提到了一些代表性框架,比如把大规模问题分解为子问题,在各子问题上分别做约束处理,再通过协同进化整合结果。这类方向目前一个公认的难点是:如何衡量分解后子问题之间的约束耦合关系。我们在做协同进化时经常遇到的情况是,单个子空间的解看似完全可行,但和其他子空间的变量协作之后,整体约束违反量突然变得很大。论文对这个问题更多是作为开放性挑战来谈。我个人的体会是,高维约束优化最容易让人误判“算法性能差”——因为问题的真实难点很大程度来自约束结构和变量耦合,而不是搜索算子本身不够好。
4.2 代理模型辅助与昂贵约束
实际工程问题里,评估一次目标与约束往往要调用昂贵的数值仿真,比如有限元计算、流体仿真,单次耗时可能从几分钟到几小时。这种场景下不可能让进化算法像跑标准测试集那样算几万次真实评估。于是代理模型辅助优化成了必由之路——用高斯过程、径向基函数这类模型近似目标与约束函数,让进化算法先在代理模型上快速搜索,再挑少量潜力高的候选点做真实昂贵评估,用获得的真实数据更新模型,循环迭代。
论文在讲这一部分时重点强调了一句我深以为然的话:代理模型本身存在误差,误差会沿着进化代际累积,可能导致算法最终被一个“虚假最优”吸引。所以在昂贵约束场景下,核心已经不只是约束处理技术本身,而是模型不确定性管理——比如基于不确定性的多准则选择、全局与局部代理混合、适应性的模型更新频率等。我把这一节读作“约束优化的计算代价问题”,它和硬件加速、并行评估一样,是让约束优化算法从论文走向工业应用的重要踏板。
4.3 动态约束与多约束并存的现实
最近“多约束优化”这个说法热度明显上来了。我理解它对应的并不仅仅是“一个问题里包含多个约束”,而是约束之间存在动态变化、冲突关系和交互作用。真实工程环境很少是静态的:原材料批次变化会改变约束界限,环境温度会移动可行域边界,甚至任务切换到不同运行模式时,整组约束可能都要重写。论文把这些归入动态约束优化问题的子类,讨论了基于记忆的重新初始化、多种群跟踪、约束变化检测与响应等应对策略。
多约束之间还存在严格的冲突。举个简单的例子,在结构设计中,重量约束和强度约束往往此消彼长,一个解很难同时让两个约束都处于“紧”的状态。这时候如果约束处理过于刚性,系统会不断淘汰掉那些在某几个约束上已经做到极致的个体,导致算法在几个约束之间反复摇摆。论文在这部分强调了对约束“结构性理解”的价值——如果能在搜索中识别哪些是主约束、哪些是辅助约束,就可以在后期针对性地松绑部分约束。这在我看来是一个实用性极强但目前研究还很不系统的方向,值得重点关注。
4.4 测试基准设计的演化
约束优化领域没有基准测试几乎是寸步难行的,综述也必然会覆盖这一块。早期研究多用CEC2006那批24个难易不一、结构各异的约束问题;后来CEC2010、CEC2017等引入更大规模、更多混合约束、带可调难度参数的问题,还出现了结合实际工程背景的测试回合。论文把基准演变和算法演化绑定起来看,指出一个很值得玩味的问题:当一个测试集在特定类型约束上设计过多时,算法容易过度专精于该类问题,换到别的结构分布上性能立刻滑坡。
这一点我要特别响应一下。我见过不少算法在CEC2017测试集上结果很漂亮,但换到真实工业约束数据上明显退化。这不完全是算法本身的诚信问题,更多是测试集覆盖不足带来的认知偏差。所以综述在最后提出“需要更多具备可解性分析、难度可调、约束结构可控的基准”,我深表赞同。对一个领域来说,基准的质量几乎决定了后续所有研究的可信度,这可能比再提出一个新算法更具长远价值。
5. 读完这篇综述,我自己整理的行动清单
5.1 从代码层面要改进什么
读综述的最大收获往往不是学会一个新算法,而是发现自己代码里“约定俗成”的做法可能存在问题。结合这篇综述,我给自己列的代码改进项包括:在约束处理模块前增加归一化前置处理;把等式约束容忍度改成可衰减的动态参数,而不是写死常量;在日志里同时记录可行种群比例、最优目标值、总约束违反度三个指标,否则后期很难诊断问题是出在搜索还是出在约束处理上。
这些改动单独看都很小,但组合起来对实验结果的影响相当大。尤其是约束归一化——很多框架只提供了约束违反度接口,并没有引导使用者做归一化处理,这导致不同问题上要手动设权重,稍不注意就会掉进数量级标尺差异的坑。我的习惯是把约束处理模块抽出来做成可插拔组件,方便在同一套代码里快速切换罚函数、可行性优先、ε约束、多目标转化等策略做横向对比。这个习惯在实验阶段帮我省了大量的重复劳动,也让我对每个算法的适用边界有了更多直觉。
5.2 适合入手的研究方向
从综述列出的开放问题看,有几个方向我认为潜力很大,也适合新研究者作为切入点:一是自适应约束处理机制,关键是尽量减少额外手调参数;二是在可分析的问题结构上做约束分解,先识别约束对搜索方向的引导作用,再决定惩罚或放宽;三是代理模型与约束处理的联合设计,让代理的不确定性尽量不干扰可行性判断;四是面向真实问题的约束优化基准构建,这个方向需要对具体工业场景有深入了解,但一旦做出来影响力会很大。
如果要我选一个最先尝试的方向,我会选“约束感知的种群多样性维护”。原因很简单:现有多样性维护大多基于决策变量或目标函数的空间分布,极少把可行域边界当作一个独立信息源使用;而约束处理中的不可行解恰恰是感知边界的天然探针。把这个探针融入多样性维护,可能在很多静态与动态约束问题上都带来改进。这是我个人从这篇综述里得到的最大启发,也准备在接下来的实验里先验证一下。
5.3 一句吐槽和一点期望
最后说说不足。综述覆盖范围很广,但对我比较关心的“约束处理与搜索算子协同设计”讨论比例仍然偏少。目前大量研究还是先设计好算子,再外接一个约束处理方法,可在高维或强耦合约束下,搜索算子本身会直接改变可行解的产生概率,这种割裂难免限制整体性能。我期望后续研究能更多地把约束信息用于塑造变异方向、指导重组对象选择,而不只是停留在事后的选择压力调整层面。
写这篇阅读笔记的时候,我恰好在一遍遍调一个带等式约束的工业问题,很多体会都是“踩在坑里”写出来的。如果这篇笔记能帮你少走几次弯路,或者让你对那些看似老生常谈的约束处理技术多一层理解,那我花的时间就值了。读综述的意义不就在这里吗——不是记住结论,而是把结论变成下一步实验的起点。