SCA逐次凸近似:非凸优化问题的工程实践与避坑指南
简介这份资源聚焦SCASequential Convex Approximation凸优化算法的实现面向具备一定数学优化基础、希望将非凸问题转化为连续凸近似求解的学习者与工程人员可用于无线通信、信号处理、能源系统优化等场景的算法验证。压缩包共2个文件均为MATLAB脚本.m整体约3KB体量轻便便于直接阅读与二次修改。其中一份脚本给出特定功率问题的示例建模另一份则承载通用SCA算法框架二者配合可帮助读者理解凸函数与凸集、凸优化问题形式、近似构造、迭代更新及收敛性分析等关键环节。目前已有2699人学习下载说明其在同类算法资料中具备一定参考价值。读者可借此掌握Taylor展开、松弛等近似技术并对照源码梳理从近似、求解到更新的完整流程进而定制适配自身问题的SCA实现。1. SCA 与凸优化从一个「非凸卡死」的现场说起如果你调过通信里的波束成形、搞过 IRS 相控阵、或者碰过机器学习里的稀疏正则大概率遇到过这种场面目标函数写出来挺漂亮一求导发现非凸CVX 直接报Disciplined convex programming error梯度下降跑一夜 loss 在几个局部极小值之间反复横跳。这时候老工程师通常会甩给你三个字母——SCASuccessive Convex Approximation逐次凸近似。它干的事很朴素既然原问题非凸那我不直接解你我在当前点附近构造一个凸的「替身」解替身拿解当新起点再构造再解直到收敛。凸优化在这里不是目的是工具SCA 是把非凸问题「翻译」成一系列凸问题的翻译官。这套方法适合谁适合手里已经有凸优化求解器CVX、CVXPY、MOSEK、SCS 都行、但被非凸约束或非凸目标卡住的从业者。下面我按自己踩过的顺序把 SCA 从原理到能跑通的代码、参数、翻车点讲一遍。2. SCA 凭什么能收敛凸近似、代理函数与三个前提2.1 非凸问题为什么不能直接丢给求解器先把话说死凸优化求解器的「凸」不是建议是硬约束。CVX 这类工具用的是 disciplined convex programming它靠一套规则判断你写的表达式是否满足凸性组合一旦出现变量相乘、变量做分母、log 里套非凹函数直接拒绝。这不是求解器弱而是凸问题的全局最优性保证依赖于可行域凸、目标凸这两个条件破坏任何一个KKT 点就不再等价于全局最优。现实里的问题偏偏爱非凸。举几个我常碰到的波束成形里功率约束下的和速率最大化速率是 log(1SINR)SINR 里分子分母都含优化变量整体非凸稀疏感知里的 L0 范数组合性质天然非凸IRS 场景里反射相移和信道耦合双线性结构。这些问题的共同点是——局部看近似凸全局看不是。SCA 的思路就是承认「全局我搞不定」转而做「局部可靠」。它在第 k 次迭代点 x_k 处找一个凸函数 g(x; x_k)满足两个条件一是 g(x_k; x_k) f(x_k)在当前点值和原函数相等二是 g(x; x_k) ≥ f(x)或 ≤取决于最大化还是最小化即代理函数是原函数的全局上界或下界。满足这两条解代理函数得到的解一定不会让原目标变差这就是单调性来源。2.2 代理函数怎么造一阶泰勒、二次上界与 MM 框架造代理函数是 SCA 的核心手艺常见三条路。第一条是一阶泰勒展开。对凸函数泰勒展开是全局下界对凹函数泰勒展开是全局上界。所以最大化一个凹函数时直接在当前点做一阶泰勒得到的就是合法的凹下界代理。这是最省事的一类很多速率最大化问题里 log(1SINR) 对某些变量是凹的直接泰勒就能用。第二条是二次上界典型场景是处理 log 和分式。比如 log(1x) 这种凹函数除了泰勒还可以用二次函数在展开点处构造上界收敛性质更好但计算稍重。分式结构常用二次变换quadratic transform把分子分母解耦成可交替优化的形式。第三条是 MM 框架Majorization-Minimization。它不要求代理函数是泰勒只要求是原函数的 majorizer上界且在当前点紧。MM 和 SCA 经常被混着叫区别在于 MM 更强调「majorize」这个构造动作SCA 更强调「逐次凸化」这个流程。实操里我基本把它们当一回事用。提示代理函数必须满足「在当前点紧」这个条件否则单调性不成立。我见过有人随手写个上界但当前点不相等结果迭代震荡查了半天以为是步长问题。2.3 收敛性依赖的三个前提缺一个就翻车SCA 的收敛保证不是白给的它依赖三个前提我按重要性排。第一代理函数在当前点必须紧且是原函数的全局上界最大化时或下界最小化时。这条破了单调性没了收敛无从谈起。第二每次子问题要解到足够精度。理论上要求解到全局最优实操里如果子问题只解了个近似外层迭代可能停在伪收敛点。CVXPY 里我会把solver的eps调紧一点别用默认的粗精度。第三迭代序列要有界或者目标函数要有下界。如果问题本身无界SCA 会一路发散。这个在功率控制里要特别注意功率上界约束必须写死。这三条里第一条是设计问题第二条是工程问题第三条是建模问题。我踩过的坑基本都落在这三类的某一类里。3. 用 Python CVXPY 跑通一个 SCA 最小例子3.1 选一个能体现非凸性的最小问题为了让你能直接抄我选一个足够小但确实非凸的问题最大化 sum(log(1 x_i * a_i))约束是 sum(x_i) ≤ Px_i ≥ 0。这里 a_i 是给定正系数x_i 是优化变量。这个问题本身其实是凹的log 是凹复合仿射保持凹所以它不算真非凸。为了制造非凸我把目标改成 sum(log(1 x_i * a_i)) - c * sum(x_i^2)加一个凹的负二次项整体就非凹了。这个结构在能效优化里很常见速率减去功耗惩罚。原问题maximize sum(log(1 a_i * x_i)) - c * sum(x_i^2) subject to sum(x_i) P x_i 0非凸来源是 -c * sum(x_i^2)它是凹函数但前面是负号整体目标变成凹减凹不保证凹。SCA 的处理是把 -c * sum(x_i^2) 在当前点做凹函数的泰勒展开得到全局上界然后最大化这个上界。3.2 代理函数的代码实现import cvxpy as cp import numpy as np np.random.seed(0) N 8 a np.random.rand(N) 0.5 c 0.1 P 5.0 x cp.Variable(N, nonnegTrue) # 原目标非凸不能直接丢给 CVXPY # obj cp.sum(cp.log(1 cp.multiply(a, x))) - c * cp.sum_squares(x) # SCA 外层迭代 x_k np.ones(N) * (P / N) # 初始点均匀分配 max_iter 50 tol 1e-4 for it in range(max_iter): # 构造代理-c*sum(x^2) 在 x_k 处的凹泰勒上界 # f(x) -c*x^2, f(x) f(x_k) f(x_k)*(x - x_k) # -c*x_k^2 - 2*c*x_k*(x - x_k) # 常数项不影响 argmax可省略 linear_term -2 * c * x_k # 梯度系数 proxy cp.sum(cp.log(1 cp.multiply(a, x))) linear_term x constraints [cp.sum(x) P] prob cp.Problem(cp.Maximize(proxy), constraints) prob.solve(solvercp.ECOS, verboseFalse) x_new x.value # 用原目标评估真实进展 true_obj np.sum(np.log(1 a * x_new)) - c * np.sum(x_new ** 2) if it % 5 0: print(fiter {it:3d} true_obj {true_obj:.6f}) if np.linalg.norm(x_new - x_k) tol: print(fconverged at iter {it}) break x_k x_new print(final x , np.round(x_new, 4))这段代码的逻辑分三层。第一层原目标里的 log 项是凹的保留不动二次项 -csum(x^2) 是凹的但我们要最大化它凹函数最大化本身没问题问题在于它和 log 项加在一起后整体不保证凹——实际上 log 是凹-x^2 也是凹两个凹相加还是凹等等这里我得纠正自己凹加凹确实是凹所以这个例子其实还是凹的。为了真正制造非凸得让二次项带正号即 csum(x^2)这样凹加凸整体非凹。我重新调整目标改成 sum(log(1 a_i * x_i)) - c * sum(x_i^2) 里把 -c 改成 c即 sum(log(1a_i x_i)) c * sum(x_i^2)最大化它。此时 log 凹x^2 凸凹加凸非凹。SCA 处理凸项 x^2 时因为要最大化凸函数的最大化不能直接做需要对凸函数做全局下界凸函数的泰勒展开是全局下界即 x^2 ≥ x_k^2 2 x_k (x - x_k)。用这个下界替换代理函数变成凹的可以最大化。# 修正后的代理构造 for it in range(max_iter): # 对凸项 c*sum(x^2) 做全局下界凸函数泰勒展开 # x^2 x_k^2 2*x_k*(x - x_k) # 常数项省略线性系数为 2*c*x_k linear_term 2 * c * x_k proxy cp.sum(cp.log(1 cp.multiply(a, x))) linear_term x constraints [cp.sum(x) P] prob cp.Problem(cp.Maximize(proxy), constraints) prob.solve(solvercp.ECOS) x_new x.value true_obj np.sum(np.log(1 a * x_new)) c * np.sum(x_new ** 2) if np.linalg.norm(x_new - x_k) tol: break x_k x_new3.3 参数怎么设初始点、步长与停止条件初始点 x_k 的选择直接影响收敛速度和能不能收敛到好点。我一般用均匀分配或者可行域内的随机点跑几次取最好的。均匀分配在功率分配问题里通常不差因为对称性。停止条件我用两个变量变化量 norm(x_new - x_k) tol或者连续两次原目标变化小于某个阈值。tol 取 1e-4 到 1e-6 之间看问题尺度。如果变量量级是 1e3tol 要相应放大。求解器选择上ECOS 适合小规模二阶锥问题SCS 适合大规模但精度粗MOSEK 最稳但要 license。CVXPY 里可以指定solvercp.ECOS如果报 solver 不支持换cp.SCS试试。注意子问题求解精度别用默认值。ECOS 默认abstol1e-8还行SCS 默认精度很粗外层迭代会被子问题的误差带偏表现为原目标曲线锯齿状。3.4 怎么验证你真的在收敛光看变量变化不够要看原目标序列。我习惯把每次迭代的真实目标打出来画一条曲线。健康的 SCA 曲线是单调上升最大化问题然后趋于平缓。如果出现下降说明代理函数构造错了或者子问题没解到最优。如果曲线一直上升不收敛检查约束是不是没写全问题可能无界。另一个验证手段是跑多个初始点看收敛到的目标值是否接近。如果差异很大说明问题有多个局部最优SCA 只能保证局部这时候要么换更好的初始点要么考虑全局化策略。4. 避坑与排查SCA 落地时最容易翻车的五件事4.1 代理函数方向搞反迭代直接发散现象原目标曲线一路下降或者震荡幅度越来越大。原因最大化问题里代理函数必须是原函数的全局上界我见过有人把凸函数的泰勒展开当上界用实际上凸函数泰勒是下界方向反了。解决每次构造完代理在当前点验证 g(x_k) f(x_k)再随机取一个点验证 g(x) f(x)最大化或 g(x) f(x)最小化。这个检查写成一个 assert能省掉大量调试时间。4.2 子问题求解精度不够伪收敛现象变量变化量很小看起来收敛了但换一个求解器或者调紧精度后目标还能再涨一截。原因子问题没解到全局最优外层迭代停在了子问题误差造成的伪驻点。解决把子问题求解器的精度调紧ECOS 用abstol1e-9, reltol1e-9SCS 用eps1e-6并增加max_iters。如果子问题规模大考虑换 MOSEK。4.3 约束非凸但被忽略解出来不可行现象求解器返回成功但把解代回原问题约束被违反。原因SCA 只凸化了目标约束里的非凸部分没处理或者处理时用了错误的近似方向。解决约束的非凸部分同样需要凸化比如 x*y b 这种双线性约束在当前点对其中一个变量做泰勒固定另一个。检查方法是把最终解代入所有原始约束逐条验证。4.4 初始点不可行第一步就报 infeasible现象CVXPY 报Problem status: infeasible。原因初始点不满足约束而代理子问题的可行域虽然包含原可行域但如果初始点离可行域太远子问题可能无解。解决初始点必须选在可行域内。功率分配里就是均匀分配相移优化里就是全零相位总之先找一个满足所有约束的点。4.5 收敛判据只看变量忽略目标尺度现象变量变化量小于 tol 但目标还在缓慢改善或者变量变化量很大但目标几乎不变。原因变量尺度和目标尺度不匹配单一判据不可靠。解决同时监控变量变化和目标变化两个都小于阈值才停。目标变化阈值取1e-6 * abs(true_obj)这种相对量比绝对量稳。5. 进阶技巧把 SCA 嵌进交替优化与加速收敛5.1 块坐标下降 SCA多变量耦合时的标准打法很多问题有多个变量块比如波束成形里的发射波束和 IRS 相移两者耦合导致联合非凸。标准做法是块坐标下降BCD固定相移优化波束固定波束优化相移每块内部用 SCA。这样每块都是凸子问题交替求解。收敛性上BCD 加 SCA 能保证目标单调但收敛速度取决于块之间的耦合强度。耦合强的时候交替次数会很多我一般设最大交替次数 20 到 50配合目标变化阈值提前停。5.2 用外推加速Nesterov 和 Anderson 加速的取舍SCA 的收敛速度通常是次线性的迭代次数多。加速手段有两类一是 Nesterov 外推在代理函数里加动量项二是 Anderson 加速用历史迭代点做线性组合。Nesterov 实现简单但步长参数不好调调不好会破坏单调性。Anderson 加速更稳但需要存历史点内存开销大。我的经验是问题规模小变量少于 100用 Anderson规模大用 Nesterov 或者干脆不加速因为加速带来的收益可能被每步的额外计算抵消。5.3 收敛性验证清单跑完 SCA我习惯做三件事确认结果可信。第一把最终解代入原问题检查所有约束满足程度违反量应该在求解器精度范围内。第二从不同初始点跑三到五次看目标值分布如果方差很小说明局部最优解质量稳定。第三把原目标曲线画出来确认单调性如果有下降段回去查代理函数。下面这张表是我常用的参数配置按问题规模分问题规模求解器子问题精度停止 tol最大迭代变量 50ECOS1e-91e-610050 ~ 500SCS1e-61e-5200 500MOSEK1e-81e-4300这张表不是金科玉律但能让你少走弯路。我早期用 SCS 默认精度跑小问题结果外层迭代 200 次还没收敛换成 ECOS 后 30 次就停了血泪经验。5.4 一个我常犯的错误最后说个我自己的教训。有次做 IRS 相移优化SCA 跑出来目标值比预期低很多查了两天以为是代理函数错了最后发现是初始相位设成了全零而全零相位在这个场景里恰好是个很差的局部点SCA 从那儿出发就再也没爬出来。后来改成随机相位跑五次取最好目标直接涨了 15%。SCA 是局部方法初始点的重要性怎么强调都不过分别在初始点上省事。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

json.loads 报 JSONDecodeError: Expecting value: line 1 column 1 (char 0),先加一行 print 看返回内容

json.loads 报 JSONDecodeError: Expecting value: line 1 column 1 (char 0),先加一行 print 看返回内容

代码跑到 json.loads() 这行报错: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)先别动解析那行。在它上面加一行,把拿到的东西打出来看: raw resp.text # 你原本要解析的东西 print(repr(raw[:100]))…

2026/10/12 4:55:53 阅读更多 →
开放式代码审查:从“LGTM”到真正有效的实践指南

开放式代码审查:从“LGTM”到真正有效的实践指南

说到 open-code-review,很多人第一反应是"开源项目的代码审查",但我在实际踩过几年坑之后,想聊的是另一个理解:把代码审查做成一种开放式的日常动作,而不是合并前被迫走过场的流程关卡。我见过太多团队把代码…

2026/10/12 4:55:53 阅读更多 →
循迹智能车和迷宫最短路径学习思考

循迹智能车和迷宫最短路径学习思考

最近在做一个智能迷宫循迹题目,之前没有接触过相关的内容。内部有一个任务,大致要求为,在一个封闭式的迷宫中,先自行运行一遍,然后在第二遍运行时,放置位置后不再进行额外的其他干预,小车自己要…

2026/10/12 4:54:53 阅读更多 →

最新新闻

mediamtx v1.21.2发布:UDP、JWT、RTSP、RTMP、HLS、WebRTC全面修复,稳定性与安全性再提升

mediamtx v1.21.2发布:UDP、JWT、RTSP、RTMP、HLS、WebRTC全面修复,稳定性与安全性再提升

2026年10月10日,mediamtx 发布 v1.21.2 最新版本。本次更新以“修复与改进”为主,覆盖通用逻辑、API、Media-Over-QUIC、RTSP、RTMP、HLS、WebRTC 以及依赖库升级等多个方向。 v1.21.2 没有引入新的功能模块,而是集中处理实际运行中可能出现的…

2026/10/12 5:43:21 阅读更多 →
哪个品牌密码锁最安全 高端市场占比领先全维安防更靠谱安心

哪个品牌密码锁最安全 高端市场占比领先全维安防更靠谱安心

在智能家居全面普及的今天,智能密码锁已经成为了家庭安全防护的核心入口。哪个品牌密码锁最安全,不仅关乎家庭财产安全,更影响着日常进出的便捷体验与全场景安防体验。2026年以来,国内智能门锁行业技术迭代加速,市场格…

2026/10/12 5:43:21 阅读更多 →
2026家用智能锁品牌推荐:德施曼热门产品深度解析

2026家用智能锁品牌推荐:德施曼热门产品深度解析

随着智能家居行业的快速发展,智能门锁已经成为了千家万户的入户安防首选。相较于传统机械锁,智能门锁不仅提供了更加便捷的多种解锁方式,还集成了猫眼可视、AI安防、远程对讲等功能,全方位提升家庭入户安全与使用体验。在2026年上…

2026/10/12 5:43:21 阅读更多 →
本地化企业知识库方案拆解:8 步把文档变成知识库

本地化企业知识库方案拆解:8 步把文档变成知识库

## 背景在项目复盘场景里,企业文档散落各处、找人问半天是效率的主要损耗点。## 核心能力- 全程本地运行,原始文档与知识数据不出电脑- 8 步流水线自动化:解析→结构化→质检→复核→分片→向量库→验收- 内置本地大模型,离线推理…

2026/10/12 5:43:21 阅读更多 →
81 极物科技 | KNX调试 - 个体地址过滤与报文隔离

81 极物科技 | KNX调试 - 个体地址过滤与报文隔离

极物科技 | KNX调试 - 个体地址过滤与报文隔离 前言 工程品质是 KNX 国际标准三十年立足全球的根基,而可观测性是品质的前提。 报文追踪把“看不见的总线”变成“看得见的证据”:每一次收发都有记录、每一次异常都有据可查。本文围绕报文追踪的接收链路、…

2026/10/12 5:43:21 阅读更多 →
百万级缺陷样本开源:工业视觉的「地基」被补上了

百万级缺陷样本开源:工业视觉的「地基」被补上了

1.工业质检的两道坎 ▍坎一:数据各管各的现成的工业缺陷数据集,几乎都窝在单一行当里。VisA、3CAD 盯着 3C 电子,PKU-GoodsAD 盯着包装,Real-IAD、MulSen-AD 盯着材料。覆盖面稍宽些的 VISION、MVTec AD、MMAD,又卡在…

2026/10/12 5:42:21 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →