最优化问题 - 内点法
以下是一种循序推理的方式,来帮助你从基础概念出发,理解 内点法(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. 问题起点:带不等式约束的优化 假设你有一个带不等式约束的优…...
vim交换文件的工作原理
在vim中,交换文件是一个临时文件,当我们使用vim打开一个文件进行编辑(一定得是做出了修改才会产生交换文件)时候,vim就会自动创建一个交换文件,而之后我们对于文件的一系列修改都是在交换文件中进行的&…...
CISCO路由基础全集
第一章:交换机的工作原理和基本技能_交换机有操作系统吗-CSDN博客文章浏览阅读1.1k次,点赞24次,收藏24次。交换机可看成是一台特殊的计算机,同样有CPU、存储介质和操作系统,只是与计算机的稍有不同。作为数据交换设备&…...
网络直播时代的营销新策略:基于受众分析与开源AI智能名片2+1链动模式S2B2C商城小程序源码的探索
摘要:随着互联网技术的飞速发展,网络直播作为一种新兴的、极具影响力的媒体形式,正逐渐改变着人们的娱乐方式、消费习惯乃至社交模式。据中国互联网络信息中心数据显示,网络直播用户规模已达到3.25亿,占网民总数的45.8…...
2024年终总结——今年是蜕变的一年
2024年终总结 摘要前因转折找工作工作的成长人生的意义 摘要 2024我从国企出来,兜兜转转还是去了北京,一边是工资低、感情受挫,一边是压力大、项目经历少,让我一度找不到自己梦寐以求的工作,我投了一家又一家ÿ…...
AutoDL 云服务器:普通 用户 miniconda 配置
AutoDL 初始状态下只有root用户,miniconda 安装在root用户目录下 /// 增加普通用户 rootautodl-container-1c0641804d-5bb7040c:~/Desktop# apt updaterootautodl-container-1c0641804d-5bb7040c:~/Desktop# apt install sudorootautodl-container-1c0641804d-5…...
渲染流程概述
渲染流程包括 CPU应用程序端渲染逻辑 和 GPU渲染管线 一、CPU应用程序端渲染逻辑 剔除操作对物体进行渲染排序打包数据调用Shader SetPassCall 和 Drawcall 1.剔除操作 视椎体剔除 (给物体一个包围盒,利用包围盒和摄像机的视椎体进行碰撞检测…...
前端力扣刷题 | 4:hot100之 子串
560. 和为K的子数组 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例: 输入:nums [1,1,1], k 2 输出:2 法一:暴力法 var subar…...
Julia 之 @btime 精准测量详解
Julia 语言因其高性能和易用性在科学计算、数据分析等领域获得了广泛关注。在性能优化中,精准测量代码执行时间是至关重要的任务,而 Julia 提供了强大的工具 btime 来辅助这一任务。本文将围绕 Julia 的 btime 来展开,帮助读者深入理解并高效…...
【Django教程】用户管理系统
Get Started With Django User Management 开始使用Django用户管理 By the end of this tutorial, you’ll understand that: 在本教程结束时,您将了解: Django’s user authentication is a built-in authentication system that comes with pre-conf…...
【机器学习】自定义数据集 使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测
一、使用pytorch框架实现逻辑回归 1. 数据部分: 首先自定义了一个简单的数据集,特征 X 是 100 个随机样本,每个样本一个特征,目标值 y 基于线性关系并添加了噪声。将 numpy 数组转换为 PyTorch 张量,方便后续在模型中…...
C语言连接Mysql
目录 C语言连接Mysql下载 mysql 开发库 方法介绍mysql_init()mysql_real_connect()mysql_query()mysql_store_result()mysql_num_fields()mysql_fetch_fields()mysql_fetch_row()mysql_free_result()mysql_close() 完整代码 C语言连接Mysql 下载 mysql 开发库 方法一…...
Windows上通过Git Bash激活Anaconda
在Windows上配置完Anaconda后,普遍通过Anaconda Prompt激活虚拟环境并执行Python,如下图所示: 有时需要连续执行多个python脚本时,直接在Anaconda Prompt下可以通过在以下方式,即命令间通过&&连接,…...
面试经典150题——图
文章目录 1、岛屿数量1.1 题目链接1.2 题目描述1.3 解题代码1.4 解题思路 2、被围绕的区域2.1 题目链接2.2 题目描述2.3 解题代码2.4 解题思路 3、克隆图3.1 题目链接3.2 题目描述3.3 解题代码3.4 解题思路 4、除法求值4.1 题目链接4.2 题目描述4.3 解题代码4.4 解题思路 5、课…...
学习数据结构(1)时间复杂度
1.数据结构和算法 (1)数据结构是计算机存储、组织数据的方式,指相互之间存在⼀种或多种特定关系的数据元素的集合 (2)算法就是定义良好的计算过程,取一个或一组的值为输入,并产生出一个或一组…...
项目集成GateWay
文章目录 1.环境搭建1.创建sunrays-common-cloud-gateway-starter模块2.目录结构3.自动配置1.GateWayAutoConfiguration.java2.spring.factories 3.pom.xml4.注意:GateWay不能跟Web一起引入! 1.环境搭建 1.创建sunrays-common-cloud-gateway-starter模块…...
【Ubuntu】使用远程桌面协议(RDP)在Windows上远程连接Ubuntu
使用远程桌面协议(RDP)在Windows上远程连接Ubuntu 远程桌面协议(RDP)是一种允许用户通过图形界面远程控制计算机的协议。本文将详细介绍如何在Ubuntu上安装和配置xrdp,并通过Windows的远程桌面连接工具访问Ubuntu。 …...
python3+TensorFlow 2.x 基础学习(一)
目录 TensorFlow 2.x基础 1、安装 TensorFlow 2.x 2、TensorFlow 2.x 基础概念 2、1 Eager Execution 2、2 TensorFlow 张量(Tensor) 3、使用Keras构建神经网络模型 3、1 构建 Sequential 模型 3、2 编译模型 1、Optimizer(优化器&a…...
《活出人生的厚度》
《活出人生的厚度》可以从不同角度来理解和实践,以下为你提供一些拓展内容: ### 不断学习与自我提升 - **持续知识更新**:保持对新知识的渴望,利用各种渠道学习,如在线课程、学术讲座、行业研讨会等。例如,…...
安装 docker 详解
在平常的开发工作中,我们经常需要部署项目。随着 Docker 容器的出现,大大提高了部署效率。Docker 容器包含了应用程序运行所需的所有依赖,避免了换环境运行问题。可以在短时间内创建、启动和停止容器,大大提高了应用的部署速度&am…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
