最优化问题 - 内点法
以下是一种循序推理的方式,来帮助你从基础概念出发,理解 内点法(Interior-Point Method, IPM) 是什么、为什么要用它,以及它是如何工作的。
1. 问题起点:带不等式约束的优化
假设你有一个带不等式约束的优化问题:
min x f ( x ) subject to g i ( x ) ≤ 0 , i = 1 , … , m . \begin{aligned} &\min_{x} \quad f(x) \\ &\text{subject to } \quad g_i(x) \le 0, \quad i=1,\ldots,m. \end{aligned} xminf(x)subject to gi(x)≤0,i=1,…,m.
- f ( x ) f(x) f(x):目标函数
- g i ( x ) ≤ 0 g_i(x) \le 0 gi(x)≤0:不等式约束(例如,控制输入不能超范围)
我们想要找到一个满足所有约束且使目标函数最小的点 x ∗ x^* x∗。
2. 直接在边界上“走”的困难
一种思路是:最优点往往在可行域边界上(很多经典优化问题里,最优解会出现在约束生效的边界)。
- 但是,如果我们只在边界上“走”,常常要先找到并跟随所有活跃约束的交线,这在高维情况下非常复杂。
- 并且,如果问题是非线性的,直接处理“在边界上走”会更难,容易出现数值不稳定或无法收敛的问题。
3. 想法:能不能“在里面”搜索,最后再逼近边界?
为了避免“一上来就卡在边界”,有人提出:
- 先在可行域内部(所有约束 g i ( x ) < 0 g_i(x) < 0 gi(x)<0 都“宽裕”)附近做搜索,那里没有太多束缚,比较容易用连续的梯度法去迭代寻优;
- 当我们逐渐找到一个更优解,需要靠近边界时,再“慢慢地”逼近它。
这样做,就不需要每一步都严格跟在边界上,也能保证可行性(不跑到约束外面去)。
4. 内点法的关键:障碍函数(Barrier Function)
为在域内部搜索,需要一种数学手段,让解“自动”不跑出界。这时就引入了障碍函数。
4.1 形式:对约束加一个“负对数”项
对每个不等式约束 g i ( x ) ≤ 0 g_i(x)\le0 gi(x)≤0,定义一个项:
− log ( − g i ( x ) ) . -\log(-g_i(x)). −log(−gi(x)).
- 如果 g i ( x ) < 0 g_i(x) < 0 gi(x)<0,那么 − g i ( x ) > 0 -g_i(x) > 0 −gi(x)>0,对数是可以求的。
- 一旦 g i ( x ) g_i(x) gi(x) 接近 0(也就是接近边界), − g i ( x ) -g_i(x) −gi(x) 趋向 0,这个对数会趋向 − ∞ -\infty −∞,但我们在目标函数中是带一个负号“-”,变成了一个正无穷大的惩罚。
- 这样一来,就相当于在可行域的边缘设置了一道**“墙”,越靠近边界,代价就越大,解被迫**留在可行域内部。
4.2 组合成“障碍型”目标函数
把原本的目标函数 f ( x ) f(x) f(x) 和障碍项结合:
B ( x , μ ) = f ( x ) − μ ∑ i = 1 m log ( − g i ( x ) ) . B(x, \mu) = f(x) - \mu \sum_{i=1}^m \log\bigl(-g_i(x)\bigr). B(x,μ)=f(x)−μi=1∑mlog(−gi(x)).
- μ > 0 \mu > 0 μ>0 是一个系数,称为“障碍参数(barrier parameter)”。
- 当 μ \mu μ 较大时,障碍惩罚也大,解就离约束边界更远;当我们逐渐减小 μ \mu μ,系统会允许解更靠近边界。
5. 迭代逼近最优解
内点法并不是一次就把问题解决,而是:
- 从一个“较宽松”的问题开始( μ \mu μ 比较大,边界惩罚很强)。
- 求解 min x B ( x , μ ) \min_x B(x, \mu) minxB(x,μ),得到一个可行域内部的解。
- 降低 μ \mu μ 的值,重新求解,这时可以允许解更加靠近(或到达)真正的最优边界。
- 多次迭代后, μ → 0 \mu \to 0 μ→0,解会逼近真实最优解。
这一过程里,算法会用到类似于 牛顿法、KKT 条件 等工具来求解各轮的子问题。
6. 内点法 vs. 其他方法
- 单纯形法(Simplex):在可行域的“顶点—边界—面”上走,比较适合线性规划;但在高维非线性问题上,效率可能较低。
- 内点法:通过“障碍函数”把解留在域内部,逐渐往边界逼近,常在非线性规划(NLP)中表现更好,也更适合大规模问题。
7. 在 MPC 中的应用
MPC 求解器(如 IPOPT)正是利用内点法来处理:
- 多步预测的系统动力学约束
- 输入/状态上下限
- 非线性目标函数
让无人机等系统在高维空间里高效地搜索最优控制输入。
🔑 小结:内点法的一句话总结
内点法是一种在可行域“内部”迭代搜索的求解策略,通过“障碍函数”阻挡解跑出可行域,并逐步放松障碍参数,最终逼近最优解和约束边界。
这就是内点法的核心“推理过程”:与其从边界开始,不如在“里层”走,让数值算法更稳定,再慢慢让解贴近约束边界,从而找到最优。
下面我将针对这段代码的逻辑和实现细节,结合“内点法(障碍函数) + 固定步长梯度下降”这一思路,做一个比较细致的解析。
1. 整体思路与算法框架
目标问题(从注释和注解上看)是:
min f ( x ) = x 1 + x 2 + x 3 s.t. x 1 2 + x 2 2 + x 3 2 ≤ 1. \begin{aligned} &\min \quad f(x) = x_1 + x_2 + x_3 \\ &\text{s.t.} \quad x_1^2 + x_2^2 + x_3^2 \;\le\; 1. \end{aligned} minf(x)=x1+x2+x3s.t.x12+x22+x32≤1.
-
可行域是单位球 { x ∈ R 3 : ∥ x ∥ ≤ 1 } \{x \in \mathbb{R}^3 : \|x\|\le 1 \} {x∈R3:∥x∥≤1};
-
希望用内点法来解决不等式约束 x 1 2 + x 2 2 + x 3 2 ≤ 1 x_1^2 + x_2^2 + x_3^2 \le 1 x12+x22+x32≤1。
通常在内点法中,会把不等式 (g(x) \le 0)(这里 g ( x ) = x 2 + y 2 + z 2 − 1 g(x)=x^2+y^2+z^2 -1 g(x)=x2+y2+z2−1 )转写成形如 (h(x) > 0),再将 (\log h(x)) 当作障碍项(barrier)。本例里定义
h ( x ) = 1 − ( x 1 2 + x 2 2 + x 3 2 ) , h(x) = 1 - (x_1^2 + x_2^2 + x_3^2), h(x)=1−(x12+x22+x32),
于是 h ( x ) > 0 h(x) > 0 h(x)>0等价于 x 1 2 + x 2 2 + x 3 2 < 1 x_1^2 + x_2^2 + x_3^2 < 1 x12+x22+x32<1。 -
内点法的障碍目标函数定义为
B ( x , μ ) = f ( x ) − μ ln ( h ( x ) ) , B(x,\mu) \;=\; f(x)\;-\;\mu \,\ln\bigl(h(x)\bigr), B(x,μ)=f(x)−μln(h(x)),
其中 μ > 0 \mu>0 μ>0 是障碍系数(barrier parameter)。 μ \mu μ 越小, − μ log h ( x ) -\mu \log h(x) −μlogh(x)的惩罚作用越强,最终会将可行解“推”到最接近边界的最优位置上。 -
在固定一个 μ \mu μ 的情况下,常用牛顿法或梯度法去最小化 B ( x , μ ) B(x,\mu) B(x,μ) 。在算法外层循环中,则逐步减小 μ \mu μ(比如乘个衰减因子),让解逐步逼近约束边界并最终得到较准确的可行最优解。
在这份代码中:
-
外层循环 (共
max_outer
次):- 每次先用当前 μ \mu μ 在球内做若干步梯度下降,尝试求解 min B ( x , μ ) \min B(x,\mu) minB(x,μ);
- 之后衰减 μ \mu μ ← \leftarrow ← μ ⋅ \mu \cdot μ⋅ (mu_decay) \text{(mu\_decay)} (mu_decay),进入下一轮;
- 重复,直到 μ \mu μ 足够小或者达到外层迭代上限。
-
内层循环 (共
max_inner
次):- 计算当前 B B B 的梯度 ∇ B ( x , μ ) \nabla B(x,\mu) ∇B(x,μ);
- 做一步固定步长的梯度下降: x ← x − α ∇ B ( x , μ ) x \leftarrow x - \alpha \nabla B(x,\mu) x←x−α∇B(x,μ);
- 如果发现新点 x new x_{\text{new}} xnew不可行(或者离边界过近),就缩小步长再试;
- 如果两次迭代 ∥ x new − x ∥ \|x_{\text{new}} - x\| ∥xnew−x∥ 非常小(<
tol
),就视为收敛并 break。
这样就得到一条渐进接近最优解的迭代轨迹,存放在 x_history
中。
2. 代码主干解析
从最外层开始看起,核心部分在函数
function x_history = interior_point_3d_solve()% 参数mu_init = 1.0; % 初始障碍参数mu_decay = 0.2; % 每轮迭代后 mu 的衰减因子alpha = 0.001; % 固定梯度下降步长tol = 1e-6; % 收敛判据max_outer= 10; % 外层循环次数max_inner= 50; % 每次 mu 下最大内层迭代次数% 初始化可行解(球内)x = [0;0;0]; mu = mu_init;x_history = [];for outer = 1:max_outerfor inner = 1:max_innerg = grad_B(x, mu); x_new = x - alpha*g;% 若越过球边界 => h(x_new) <= 0if h_3d(x_new) <= 1e-9x_new = x - 0.1*alpha*g; % 缩小步长再试end% 收敛判断if norm(x_new - x) < tolx = x_new;break; % 跳出内层循环endx = x_new;x_history = [x_history; x']; end% 减小 mumu = mu * mu_decay;if mu < 1e-12break; % mu 已经很小,不必再迭代endend% 加入最终点x_history = [x_history; x'];
end
mu_init
设为 1.0,之后每次外层循环会mu = mu * mu_decay
,即乘以 0.2。这样大概迭代几次后就会让mu
变得很小。alpha=0.001
是固定的梯度下降步长,相对比较小,所以我们用到max_inner=50
步来让它收敛到一个合适精度。- 收敛阈值
tol=1e-6
:若相邻两步 ∥ x new − x ∥ \|x_{\text{new}}-x\| ∥xnew−x∥ 小于这个值,就认为内层已经收敛。 - 每次更新
x
后都会把它记录到x_history
里,用于可视化迭代轨迹。
这里值得注意的是:如果单纯用固定步长,可能碰到越过可行域边界(即 (x2+y2+z^2>1))的风险。为此,代码做了一个简单检查:
if h_3d(x_new) <= 1e-9x_new = x - 0.1*alpha*g; % 步长缩小10倍
end
当然,这只是一个很“简单粗暴”的处理,工业级内点法通常要做更精细的线搜索或牛顿校正,这里是为了示例演示。
3. 障碍函数与梯度的计算
3.1 h_3d(x)
function val = h_3d(x)val = 1.0 - (x(1)^2 + x(2)^2 + x(3)^2);
end
即 h ( x ) = 1 − r 2 h(x) = 1 - r^2 h(x)=1−r2,其中 r 2 = x 1 2 + x 2 2 + x 3 2 r^2 = x_1^2 + x_2^2 + x_3^2 r2=x12+x22+x32。球内保证 h ( x ) > 0 h(x)>0 h(x)>0。
3.2 B_3d(x, mu)
function val = B_3d(x, mu)val = f_3d(x) - mu*log(h_3d(x));
end
对应障碍目标 B ( x , μ ) = f ( x ) − μ ln ( h ( x ) ) B(x,\mu) = f(x) - \mu\ln(h(x)) B(x,μ)=f(x)−μln(h(x))。
3.3 grad_B(x, mu)
的推导
从数学上看,如果
B ( x , μ ) = f ( x ) − μ ln ( h ( x ) ) , B(x,\mu) \;=\; f(x) \;-\; \mu \,\ln\bigl(h(x)\bigr), B(x,μ)=f(x)−μln(h(x)),
则其梯度为
∇ B ( x , μ ) = ∇ f ( x ) − μ ∇ ln ( h ( x ) ) . \nabla B(x,\mu) = \nabla f(x) \;-\; \mu \,\nabla \ln\bigl(h(x)\bigr). ∇B(x,μ)=∇f(x)−μ∇ln(h(x)).
其中
∇ ln ( h ( x ) ) = 1 h ( x ) ∇ h ( x ) . \nabla \ln(h(x)) = \frac{1}{h(x)} \nabla h(x). ∇ln(h(x))=h(x)1∇h(x).
而 (h(x) = 1 - r^2),(\nabla h(x) = -2x)。所以
∇ ln ( h ( x ) ) = − 2 x 1 − r 2 . \nabla \ln(h(x)) = \frac{-2x}{1-r^2}. ∇ln(h(x))=1−r2−2x.
带上负号“ − μ -\mu −μ”一起,就得到对障碍项的贡献为 + 2 μ x 1 − r 2 +\frac{2\mu x}{1 - r^2} +1−r22μx。
如果我们要最小化 f ( x ) = x 1 + x 2 + x 3 f(x)= x_1 + x_2 + x_3 f(x)=x1+x2+x3,其梯度就是 ( 1 , 1 , 1 ) (1,1,1) (1,1,1)。
于是
∇ B ( x , μ ) = ( 1 , 1 , 1 ) + 2 μ 1 − r 2 ( x 1 , x 2 , x 3 ) . \nabla B(x,\mu) = \bigl(1,1,1\bigr) + \frac{2\mu}{1-r^2}\,\bigl(x_1,x_2,x_3\bigr). ∇B(x,μ)=(1,1,1)+1−r22μ(x1,x2,x3).
在代码中,可以看到:
function g = grad_B(x, mu)hx = h_3d(x); % 1 - r^2dB_dx0 = 1.0 + (2.0 * mu * x(1) / hx);dB_dx1 = 1.0 + (2.0 * mu * x(2) / hx);dB_dx2 = 1.0 + (2.0 * mu * x(3) / hx);g = [dB_dx0; dB_dx1; dB_dx2];
end
正好对应上面的公式:1.0
就是 ∇ f ( x ) \nabla f(x) ∇f(x) 的那一部分, ( 2.0 ∗ m u ∗ x ( i ) / h x ) (2.0*mu*x(i)/hx) (2.0∗mu∗x(i)/hx) 对应障碍项梯度那一部分。
4. 运行与结果
如果修正了 f_3d
,那么在球内最小化 (x+y+z) 的最优解,理论上会落在球面上与 ((1,1,1)) 方向相反的地方,也就是球面朝着 ((-1,-1,-1)) 的方向。其最优解应当是
( − 1 3 , − 1 3 , − 1 3 ) \left(-\frac{1}{\sqrt{3}}, \;-\frac{1}{\sqrt{3}}, \;-\frac{1}{\sqrt{3}}\right) (−31,−31,−31)
因为在约束 x 2 + y 2 + z 2 = 1 x^2+y^2+z^2=1 x2+y2+z2=1 上,(x+y+z) 的最小值就是 − 3 -\sqrt{3} −3。迭代跑起来后,你应该能看到解最终趋近这个点,轨迹会从球心出发,一路在球内前进,并在迭代后期逐渐贴近球面。
如果把可视化部分加上(即下面这段示例):
x_history = interior_point_3d_solve();figure('Color','w','Name','Interior-Point 3D Demo');
hold on; grid on; axis equal;% 绘制单位球面
[Xs, Ys, Zs] = sphere(50);
surf(Xs, Ys, Zs, ...'FaceAlpha',0.1, 'EdgeColor','none', 'FaceColor','c');xlabel('x_0'); ylabel('x_1'); zlabel('x_2');
title('Minimize x_0 + x_1 + x_2 subject to x_0^2 + x_1^2 + x_2^2 \le 1');% 画迭代轨迹
x0_hist = x_history(:,1);
x1_hist = x_history(:,2);
x2_hist = x_history(:,3);
plot3(x0_hist, x1_hist, x2_hist, 'b-o','LineWidth',1.5);% 最后一点标红
plot3(x0_hist(end), x1_hist(end), x2_hist(end), ...'ro', 'MarkerSize',8, 'MarkerFaceColor','r');legend('Unit Sphere','Iter Process','Final Solution');
view(35,25);
就能看到一个球面和从原点出发,沿着负对角线方向慢慢收敛到球面那一点的轨迹。
5. 小结
-
内点法原理:通过把约束 x 1 2 + x 2 2 + x 3 2 ≤ 1 x_1^2 + x_2^2 + x_3^2 \le 1 x12+x22+x32≤1 转化为对数障碍 − μ ln ( 1 − r 2 ) -\mu \ln\bigl(1 - r^2\bigr) −μln(1−r2),并在外层迭代不断减小 μ \mu μ。这能保证迭代点始终在球内 ( h ( x ) > 0 h(x) > 0 h(x)>0),同时在 μ → 0 \mu\to0 μ→0 时逐渐收敛到可行域边界上的最优点。
-
实现细节:
- 用固定步长 + 简单可行性校正(越界时缩步长);
- 用
max_outer
与max_inner
控制多重循环; - 用
tol
判断迭代收敛; - 在每次迭代都记录
x
到x_history
中,用于可视化。
-
需要修正的地方:
代码中的f_3d(x)
与注释/梯度公式不一致,应改回function val = f_3d(x)val = x(1) + x(2) + x(3); end
这样才与“最小化 (x+y+z)”的需求相吻合。
修正后运行,即可得到一个从球心(原点)出发,最终靠近 ( − 1 3 , − 1 3 , − 1 3 ) \bigl(-\frac{1}{\sqrt{3}},-\frac{1}{\sqrt{3}},-\frac{1}{\sqrt{3}}\bigr) (−31,−31,−31) 的迭代过程。
参考:为什么最优解是 ( − 1 / 3 , − 1 / 3 , − 1 / 3 ) \bigl(-1/\sqrt{3},-1/\sqrt{3},-1/\sqrt{3}\bigr) (−1/3,−1/3,−1/3)?
因为在单位球约束下,若要最小化 x 1 + x 2 + x 3 x_1+x_2+x_3 x1+x2+x3,相当于“在球面上找与(1,1,1)方向夹角最大的点”——也就是与 ( 1 , 1 , 1 ) (1,1,1) (1,1,1) 反方向的单位向量。它正好是 − 1 3 ( 1 , 1 , 1 ) \frac{-1}{\sqrt{3}}(1,1,1) 3−1(1,1,1)。目标值是
x 1 + x 2 + x 3 = − 3 . x_1 + x_2 + x_3 = -\sqrt{3}. x1+x2+x3=−3.
这与几何直觉、拉格朗日乘子法都能得到一样的结果。
6. 结语
- 该代码很好地演示了使用对数障碍(log-barrier)的内点法思路:用一系列的无约束子问题(带障碍项)来逼近有约束优化,并在外层迭代中逐渐减小障碍系数 (\mu),使解贴近约束边界的最优解。
- 不过,在正式应用时,往往不会用固定步长的简单梯度下降,而会用牛顿法或线搜索,以获得更好的数值稳定性和收敛速度。
- 代码本身最大的问题是
f_3d
与注释/公式不匹配,只要改回f_3d(x) = x(1)+x(2)+x(3)
即可与文档保持一致,也能正确体现“最小化 ∑ x i \sum x_i ∑xi”的意图。
在使用对数障碍(log‐barrier)形式的内点法时, μ \mu μ(有时也记作 t t t 或 ν \nu ν)通常被称为障碍参数(barrier parameter)。它的核心作用是:
-
控制对数障碍项的“强度”
在障碍型目标函数
B ( x , μ ) = f ( x ) − μ ln ( h ( x ) ) B(x,\mu) \;=\; f(x)\;-\;\mu \,\ln\bigl(h(x)\bigr) B(x,μ)=f(x)−μln(h(x))
中,(\mu) 决定了 (-\mu \ln\bigl(h(x)\bigr)) 这部分惩罚力度的大小。- 当 (\mu) 较大时,对(\ln(h(x)))的惩罚力度相对较小,算法对靠近约束边界的“敏感度”不高,所以在收敛初期可以更自由地在可行域里移动。
- 当 (\mu) 变小时,(-\mu \ln(h(x)))会变得更尖锐,迫使解更加贴近且“贴合”可行域的边界(若这是最优解所在的位置)。
-
帮助逐步逼近最优解并保持可行
内点法的思路是:一开始用较大的 (\mu)(障碍作用较弱)来保证算法稳步地在可行域里进行搜索;之后在外层循环中逐步减小 (\mu),使对数障碍项逐渐变得陡峭,从而把解“推”到真正需要的边界附近并逼近最优解。 -
数值上的平衡
- 如果 (\mu) 过小,一开始 (-\mu \ln(h(x))) 的势垒就会非常强,导致很难在可行域里移动,且容易产生数值不稳定(如(\ln(h(x)))趋向负无穷)。
- 如果 (\mu) 过大,到收敛后期也无法精确地在边界附近找到最优解。所以通常会有一条**“(\mu)衰减”路径**(比如 (\mu \leftarrow \beta \mu),(\beta<1))来让解逐步逼近最优值。
简而言之:(\mu) 是控制“障碍强度”的调节器。随着 (\mu) 从大到小的不断衰减,解会逐渐向可行域边界靠拢并最终获得精确的约束最优解。
完整代码
function x_history = interior_point_3d_solve()
%{使用内点法(障碍函数 + 固定步长梯度下降)求解:min f(x) = x(1) + x(2) + x(3)s.t. x(1)^2 + x(2)^2 + x(3)^2 <= 1.内点法: 定义障碍型目标B(x, mu) = f(x) - mu * log( h(x) ), 其中h(x) = 1 - (x0^2 + x1^2 + x2^2).输出:x_history: 每个迭代得到的 (x0, x1, x2).
%}% 参数mu_init = 1.0; % 初始障碍参数mu_decay = 0.2; % 每轮迭代后 mu 的衰减因子alpha = 0.001; % 梯度下降步长tol = 1e-6; % 收敛阈值max_outer = 10; % 外层循环(更新 mu)次数max_inner = 50; % 每次 mu 下最大迭代次数% 初始化可行解 (x0, x1, x2),球内,例如原点x = [0; 0; 0]; mu = mu_init;x_history = [];for outer = 1:max_outerfor inner = 1:max_innerg = grad_B(x, mu); % 计算梯度x_new = x - alpha*g;% 如果越过球边界 => h(x_new) <= 0 => x_new^2+y^2+z^2 >=1% 简单地缩小步长再试if h_3d(x_new) <= 1e-9x_new = x - 0.1*alpha*g;end% 收敛判断if norm(x_new - x) < tolx = x_new;break;endx = x_new;x_history = [x_history; x']; % 记录轨迹(行向量)end% 降低 mu 使解更逼近约束边界mu = mu * mu_decay;if mu < 1e-12break;endend% 最后再将最终点加入x_history = [x_history; x'];
end%% 目标函数 f(x)
function val = f_3d(x)% f(x0, x1, x2) = x0 + x1 + x2val = x(1) + x(2) + x(3);
end%% 障碍函数项 h(x) = 1 - (x0^2 + x1^2 + x2^2)
function val = h_3d(x)val = 1.0 - (x(1)^2 + x(2)^2 + x(3)^2);
end%% 障碍型目标 B(x, mu) = f(x) - mu*ln(h(x))
function val = B_3d(x, mu)val = f_3d(x) - mu*log(h_3d(x));
end%% B(x, mu) 的梯度
function g = grad_B(x, mu)
%{B(x) = (x0 + x1 + x2) - mu * ln(1 - r^2),其中 r^2 = x0^2 + x1^2 + x2^2=> dB/dx0 = 1 + [2 mu x0 / (1 - r^2)]=> dB/dx1 = 1 + [2 mu x1 / (1 - r^2)]=> dB/dx2 = 1 + [2 mu x2 / (1 - r^2)]
%}hx = h_3d(x);r2 = x(1)^2 + x(2)^2 + x(3)^2;% hx = 1 - r2 > 0 (只要在球内)dB_dx0 = 1.0 + (2.0 * mu * x(1) / hx);dB_dx1 = 1.0 + (2.0 * mu * x(2) / hx);dB_dx2 = 1.0 + (2.0 * mu * x(3) / hx);g = [dB_dx0; dB_dx1; dB_dx2];
end%{演示如何在 3D 中用“障碍函数 + 简单梯度下降”的内点法来最小化 f(x) = x0 + x1 + x2subject to x0^2 + x1^2 + x2^2 <= 1.可行域是单位球 (x0^2 + x1^2 + x2^2 <= 1)。我们会在图中绘制球面,并用散点绘制迭代轨迹。
%}% 1) 调用求解函数,得到每步迭代的解 x(k)
x_history = interior_point_3d_solve();% 2) 可视化
figure('Color','w','Name','Interior-Point 3D Demo');
hold on; grid on; axis equal; % 3D 坐标中,最好设 axis equal% 2.1 绘制单位球面(x0^2 + x1^2 + x2^2 = 1)
[Xs, Ys, Zs] = sphere(50);
% sphere() 生成一个半径为 1 的球面网格
surf(Xs, Ys, Zs, 'FaceAlpha',0.1, 'EdgeColor','none', 'FaceColor','c');
% 给球面一个半透明的青色xlabel('x_0'); ylabel('x_1'); zlabel('x_2');
title('Minimize x_0 + x_1 + x_2 subject to x_0^2 + x_1^2 + x_2^2 \le 1');% 2.2 绘制迭代轨迹
x0_hist = x_history(:,1);
x1_hist = x_history(:,2);
x2_hist = x_history(:,3);nPoints = size(x_history,1);
if nPoints > 1% 中间过程点用蓝色散点plot3(x0_hist(1:end-1), x1_hist(1:end-1), x2_hist(1:end-1), ...'bo-', 'LineWidth',1.5, 'MarkerSize',4, 'MarkerFaceColor','b');
end% 最后一点用红色标记
plot3(x0_hist(end), x1_hist(end), x2_hist(end), ...'ro', 'MarkerSize',8, 'MarkerFaceColor','r');legend('Unit Sphere (Constraint)', 'Iter Process', 'Final Solution');
view(35, 25); % 调整3D视角
相关文章:
最优化问题 - 内点法
以下是一种循序推理的方式,来帮助你从基础概念出发,理解 内点法(Interior-Point Method, IPM) 是什么、为什么要用它,以及它是如何工作的。 1. 问题起点:带不等式约束的优化 假设你有一个带不等式约束的优…...
Vue5---
目录 一、学习目标 1.自定义指令 2.插槽 3.综合案例:商品列表 4.路由入门 二、自定义指令 1.指令介绍 2.自定义指令 3.自定义指令的语法 三、自定义指令-指令的值 1.需求 2.语法 3.代码示例 五、插槽-默认插槽 1.作用 2.需求 4.使用插槽的基本语法…...
Helm Chart 实战指南
Helm 是 Kubernetes 的包管理工具,而 Helm Chart 是 Helm 的核心概念,用于定义、安装和升级 Kubernetes 应用。本文将带你从零开始,通过实战演练,掌握 Helm Chart 的创建、配置和部署,帮助你高效管理 Kubernetes 应用。 1. 环境准备 在开始之前,确保你已经具备以下环境:…...
如何写一篇高质量的提示词?
不管是产品经理还是使用AI工具的用户,很多时候的烦恼是如何写提示词,我觉得写提示词就是在梳理思路,下边是一个提示词的结果,OpenAI 的总裁 Greg Brockman 曾转发过这个结构。 这种结构可以创建一个清晰、简洁、可执行的提示&…...
系统架构设计师教材:信息系统及信息安全
信息系统 信息系统的5个基本功能:输入、存储、处理、输出和控制。信息系统的生命周期分为4个阶段,即产生阶段、开发阶段、运行阶段和消亡阶段。 信息系统建设原则 1. 高层管理人员介入原则:只有高层管理人员才能知道企业究竟需要什么样的信…...
在Windows系统中本地部署属于自己的大语言模型(Ollama + open-webui + deepseek-r1)
文章目录 1 在Windows系统中安装Ollama,并成功启动;2 非docker方式安装open-webui3下载并部署模型deepseek-r1 Ollama Ollama 是一个命令行工具,用于管理和运行机器学习模型。它简化了模型的下载与部署,支持跨平台使用,…...
使用Redis生成全局唯一ID示例
全局ID生成器,一种在分布式系统下用来生成全局唯一ID的工具,一般满足一下要求特性 1.唯一性 2.高性能 3.安全性 4.递增性 5.高可用 Component public class RedisIdWorker {/*** 定义一个开始的时间戳(秒级)* param args*/private static final long BEGIN_TIMESTAMP 16…...
【llm对话系统】 LLM 大模型推理python实现:vLLM 框架
在 LLM 的应用中,推理 (Inference) 阶段至关重要。它指的是利用训练好的 LLM 模型,根据输入 (Prompt) 生成文本的过程。然而,LLM 的推理速度往往较慢,尤其是在处理长序列或高并发请求时,效率瓶颈尤为突出。 为了解决这…...
16.Word:石油化工设备技术❗【28】
目录 题目 NO1.2 NO3 NO4 题目 NO1.2 F12:另存为将“Word素材.docx”文件另存为“Word. docx”(“docx”为文件扩展名) 光标来到表格上方→插入→形状→新建画布→单击选中→格式→高度/宽度(格式→大小对话框→取消勾选✔锁定…...
《多阶段渐进式图像修复》学习笔记
paper:2102.02808 GitHub:swz30/MPRNet: [CVPR 2021] Multi-Stage Progressive Image Restoration. SOTA results for Image deblurring, deraining, and denoising. 目录 摘要 1、介绍 2、相关工作 2.1 单阶段方法 2.2 多阶段方法 2.3 注意力机…...
Oracle、PostgreSQL该学哪一个?
从事数据库运维一线工作的老鸟,经常会有人来问我:“Oracle 和 PostgreSQL,我该学哪个?哪个更有职业发展前景?” 今天就来和大家好好唠唠。 先说说 Oracle。它堪称数据库领域的 “老牌贵族”,功能极其强大。…...
SpringCloud系列教程:微服务的未来(十七)监听Nacos配置变更、更新路由、实现动态路由
前言 在微服务架构中,API 网关是各个服务之间的入口点,承担着路由、负载均衡、安全认证等重要功能。为了实现动态的路由配置管理,通常需要通过中心化的配置管理系统来实现灵活的路由更新,而无需重启网关服务。Nacos 作为一个开源…...
第十六届蓝桥杯大赛软件赛(编程类)知识点大纲
目录 大学 C 组 大学 B 组 研究生及大学 A 组 说明: 大学 C 组 1. 枚举:难度:[1-3] 2. 排序 冒泡排序:难度 2选择排序:难度 3插入排序:难度 3 3. 搜索 广度优先搜索(BFS)&a…...
商品信息管理自动化测试
目录 前言 一、思维导图 二、代码编写 1.在pom.xml文件中添加相关依赖 2.自动化代码编写 三、代码测试 小结 前言 1. 针对商品信息管理项目进行测试,商品信息管理项目主要有商品列表页、部门列表页、员工列表页,主要功能:对商品信息的…...
批量卸载fnm中已经安装的所有版本
直接上代码 fnm list | awk -F NR>1 {print line} {line$2} | xargs -n 1 -I {} fnm uninstall {}原理 fnm list 列出 fnm 中所有已经安装的 node 版本 awk -F NR>1 {print line} {line$2} 以空格分隔-F {line$2},取从左到右第 2 段(v22.11…...
有一对兔子,从出生后第三个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
# 分析:兔子从第三个月起增加一对,前两个月1对,三月份2对,4月份3对,5月份5对,6月份8对,7月份13个,以此类推每个月的兔子总数是前两月的兔子数的和。 def fibonacci(n): # 定义了斐波…...
ReactNative react-devtools 夜神模拟器连调
目录 一、安装react-devtools 二、在package.json中配置启动项 三、联动 一、安装react-devtools yarn add react-devtools5.3.1 -D 这里选择5.3.1版本,因为高版本可能与夜神模拟器无法联动,导致部分功能无法正常使用。 二、在package.json中配置启…...
【Unity教程】零基础带你从小白到超神part3
粒子系统 在创建粒子系统之前,需要先添加一些粒子样式,这可以在资源商店中通过导入官方提供的StandardAssets资源包得到。完成资源的导入后,该资源包中的StandardAssets>ParticleSystems>Prefabs文件夹下包含多种成品粒子效果…...
[Java]快速入门
java是什么 Java是美国的sun 公司(Stanford University Network)在1995年推出的一门计算机高级编程语言 sun公司于2009年被Oracle(甲骨文)公司收购。 普遍认同lava的联合创始人之一: 詹姆斯高斯林(James Gosling)为Java之父。 Java是世界上最流行的编程语言之一,…...
慕课:若鱼1919的视频课程:Java秒杀系统方案优化 高性能高并发实战,启动文档
代码: Javahhhh/miaosha191: 运行成功了慕课若鱼1919的视频课程:Java秒杀系统方案优化 高性能高并发实战https://github.com/Javahhhh/miaosha191 https://github.com/Javahhhh/miaosha191 miaosha项目启动文档 需安装的配置环境: VMwar…...
stack 和 queue容器的介绍和使用
1.stack的介绍 1.1stack容器的介绍 stack容器的基本特征和功能我们在数据结构篇就已经详细介绍了,还不了解的uu, 可以移步去看这篇博客哟: 数据结构-栈数据结构-队列 简单回顾一下,重要的概念其实就是后进先出,栈在…...
Kafka的内部通信协议
引言 kafka内部用到的常见协议和优缺点可以看看原文 Kafka用到的协议 本文奖详细探究kafka核心通信协议和高性能的关键 网络层通信的实现 基于 Java NIO:Kafka 的网络通信层主要基于 Java NIO 来实现,这使得它能够高效地处理大量的连接和数据传输。…...
【论文投稿-第八届智能制造与自动化学术会议(IMA 2025)】HTML, CSS, JavaScript:三者的联系与区别
大会官网:www.icamima.org 目录 前言 一、HTML(超文本标记语言):网页的骨架 HTML 的作用: 例子: 总结: 二、CSS(层叠样式表):网页的外观设计 CSS 的…...
解锁豆瓣高清海报:深度爬虫与requests进阶之路
前瞻 PosterBandit 这个脚本能够根据用户指定的日期,爬取你看过的影视最高清的海报,并自动拼接成指定大小的长图。 你是否发现直接从豆瓣爬取下来的海报清晰度很低? 使用 .pic .nbg img CSS 选择器,在 我看过的影视 界面找到图片…...
大数据治理实战:架构、方法与最佳实践
📝个人主页🌹:一ge科研小菜鸡-CSDN博客 🌹🌹期待您的关注 🌹🌹 1. 引言 大数据治理是确保数据质量、合规性和安全性的重要手段,尤其在数据驱动决策和人工智能应用日益普及的背景下&…...
03链表+栈+队列(D1_链表(D1_基础学习))
目录 一、什么是链表 二、基本操作 三、为什么要使用链表 四、为什么能够在常数时间访问数组元素 数组优点 数组缺点 五、动态数组诞生 链表优点 链表缺点 六、链表、数组和动态数组的对比 七、 链表种类 1. 单向链表 2. 双向链表 3. 循环链表 八、链表衍生 ...…...
芯片AI深度实战:进阶篇之vim内verilog实时自定义检视
本文基于Editor Integration | ast-grep,以及coc.nvim,并基于以下verilog parser(my-language.so,文末下载链接), 可以在vim中实时显示自定义的verilog 匹配。效果图如下: 需要的配置如下: 系列文章: 芯片…...
【计算机网络】host文件
host文件的主要功能: 域名解析 本地映射:host文件的主要功能是将**域名映射到相应的 IP 地址**。当计算机需要访问一个网站或服务时,它会首先在 host文件中查找该域名对应的 IP 地址。如果在 host文件中找到了匹配的域名和 IP 地址映射&…...
算法随笔_31:移动零
上一篇:算法随笔_30: 去除重复字母-CSDN博客 题目描述如下: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,…...
知识图谱的动态演化与进化策略
目录 前言1. 数据补充与更新策略1.1 数据源扩展1.2 实体与关系更新1.3 流数据处理 2. 数据质量保障与清洗2.1 数据清洗2.2 数据融合2.3 质量评估 3. 规则与模型优化3.1 规则学习与优化3.2 模型更新3.3 推理能力增强 4. 知识验证与反馈机制4.1 用户反馈机制4.2 知识验证机制 5. …...
C ++ 1
静态变量和全局变量、局部变量的区别、在内存上是怎么分布的 静态局部变量 ● 特点: ○ 作用域:仅限于声明它们的函数或代码块内部。 ○ 生命周期:静态局部变量在程序的整个运行期间都存在,只初始化一次(在第一次使用…...
mybatis(134/134)完结
一级缓存(默认情况下开启)同一个sqlsession中执行相同的查询语句走一级缓存 二级缓存 :同一个sqlsessionfactory,sqlsession关闭了才会将一级缓存提交到二级缓存中 外部编写的缓存 PageHelper插件:方便进行分页&#x…...
SQL注入漏洞之错误类型注入 爆破表 字段 列名称 以及mysql版本 以及Limit使用方式解释 以及靶场相关联系
目录 Msql函数常用函数 基本变量函数 报错注入 报错注入什么时候用? 报错注入函数 报错注入语句-这是重点 报错性注入实战 案例1 爆数据库中的表 案例2 表名称 案例3 表字段 Limit用法解释: Msql函数常用函数 基于msql的基本变量可以学习常用函数是为了…...
k均值聚类将数据分成多个簇
K-Means 聚类并将数据分成多个簇,可以使用以下方法: 实现思路 随机初始化 K 个聚类中心计算每个点到聚类中心的距离将点分配到最近的簇更新聚类中心重复上述过程直到收敛 完整代码: import torch import matplotlib.pyplot as pltdef kme…...
智能工厂能耗管理:Python助力节能增效
智能工厂能耗管理:Python助力节能增效 在工业4.0时代,工厂能耗管理已成为制造企业降本增效的重要一环。传统的能耗管理方式往往依赖人工统计和经验决策,导致能源浪费严重。而借助人工智能与Python的强大能力,我们可以实现智能化、数据驱动的能耗优化方案。今天,我们就来聊…...
【汽车电子架构】AutoSAR从放弃到入门专栏导读
本文是汽车电子架构:AutoSAR从放弃到入门专栏的导读篇。文章延续专栏文章的一贯作风,从概念与定义入手,希望读者能对AutoSAR架构有一个整体的认识,然后对专栏涉及的文章进行分类与链接。本文首先从AutoSAR汽车软件架构的概念&…...
【go语言】指针
一、指针的定义和使用 在 Go 语言中,指针是一种变量,用来存储另一个变量的内存地址。通过指针,我们可以间接地操作其他变量的值。Go 语言中的指针与其他语言(如 C 或 C)的指针有所不同,它不支持指针算术&am…...
宝塔面板SSL加密访问设置教程
参考:https://www.bt.cn/bbs/thread-117246-1-1.html 如何快速使用证书加密访问面板 因早期默认未开启https访问所以没有相关的风险提醒,现面板默认已开启https加密访问、提升安全性 由于采用的是服务器内部本身签发证书,不被公网浏览器信任请参考以下步…...
spring中解决循环依赖的方法
为了避免这种循环依赖问题,Spring 引入了三级缓存的机制,分为: 一级缓存(singletonObjects):这是存放已经完全创建好的单例 Bean 的缓存。当 Bean 完全初始化并且可以被使用时,会存放在这里。 …...
新时代架构SpringBoot+Vue的理解(含axios/ajax)
文章目录 引言SpringBootThymeleafVueSpringBootSpringBootVue(前端)axios/ajaxVue作用响应式动态绑定单页面应用SPA前端路由 前端路由URL和后端API URL的区别前端路由的数据从哪里来的 Vue和只用三件套axios区别 引言 我是一个喜欢知其然又知其所以然的…...
Docker/K8S
文章目录 项目地址一、Docker1.1 创建一个Node服务image1.2 volume1.3 网络1.4 docker compose 二、K8S2.1 集群组成2.2 Pod1. 如何使用Pod(1) 运行一个pod(2) 运行多个pod 2.3 pod的生命周期2.4 pod中的容器1. 容器的生命周期2. 生命周期的回调3. 容器重启策略4. 自定义容器启…...
新年快乐!给大家带来了一份 python 烟花代码!
大家好,我是菲英。 今天带来一份 python 代码,是简易的烟花小程序。 安装包 pip install pygame进入正题 - 我们的烟花代码: import pygame import random import math# 初始化pygame pygame.init()# 设置屏幕大小和标题 screen pygame.…...
iperf 测 TCP 和 UDP 网络吞吐量
注:本文为 “iperf 测网络吞吐量” 相关文章合辑。 未整理去重。 使用 iperf3 监测网络吞吐量 Tom 王 2019-12-21 22:23:52 一 iperf3 介绍 (1.1) iperf3 是一个网络带宽测试工具,iperf3 可以擦拭 TCP 和 UDP 带宽质量。iperf3 可以测量最大 TCP 带宽…...
(1)Linux高级命令简介
Linux高级命令简介 在安装好linux环境以后第一件事情就是去学习一些linux的基本指令,我在这里用的是CentOS7作演示。 首先在VirtualBox上装好Linux以后,启动我们的linux,输入账号密码以后学习第一个指令 简介 Linux高级命令简介ip addrtou…...
LeetCode:96.不同的二叉搜索树
跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的! 代码随想录 LeetCode:96.不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉…...
Linux学习笔记——用户管理
一、用户管理命令 useradd #用户增加命令 usermod #用户修改命令 passwd #密码修改命令 userdel #用户删除命令 su #用户提权命令 1、useradd命令(加用户): 创建并设置用户信息,使用us…...
Baklib揭示内容中台与人工智能技术的创新协同效应
内容概要 在当今信息爆炸的时代,内容的高效生产与分发已成为各行业竞争的关键。内容中台与人工智能技术的结合,为企业提供了一种新颖的解决方案,使得内容创造的流程更加智能化和高效化。 内容中台作为信息流动的核心,能够集中管…...
FreeRTOS从入门到精通 第十四章(队列集)
参考教程:【正点原子】手把手教你学FreeRTOS实时系统_哔哩哔哩_bilibili 一、队列集简介 1、队列集概述 (1)一个队列只允许任务间传递的消息为同一种数据类型,如果需要在任务间传递不同数据类型的消息时,那么就可以…...
Python实现U盘数据自动拷贝
功能:当电脑上有U盘插入时,自动复制U盘内的所有内容 主要特点: 1、使用PyQt5创建图形界面,但默认隐藏 2、通过CtrlAltU组合键可以显示/隐藏界面 3、自动添加到Windows启动项 4、监控USB设备插入 5、按修改时间排序复制文件 6、静…...
Vue.js 什么是 Composition API?
Vue.js 什么是 Composition API? 今天我们来聊聊 Vue 3 引入的一个重要特性:组合式 API(Composition API)。如果你曾在开发复杂的 Vue 组件时感到代码难以维护,那么组合式 API 可能正是你需要的工具。 什么是组合式 …...