最优化问题 - 内点法

以下是一种循序推理的方式,来帮助你从基础概念出发,理解 内点法(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=1mlog(gi(x)).

  • μ > 0 \mu > 0 μ>0 是一个系数,称为“障碍参数(barrier parameter)”。
  • μ \mu μ 较大时,障碍惩罚也大,解就离约束边界更远;当我们逐渐减小 μ \mu μ,系统会允许解更靠近边界。

5. 迭代逼近最优解

内点法并不是一次就把问题解决,而是:

  1. 从一个“较宽松”的问题开始 μ \mu μ 比较大,边界惩罚很强)。
  2. 求解 min ⁡ x B ( x , μ ) \min_x B(x, \mu) minxB(x,μ),得到一个可行域内部的解。
  3. 降低 μ \mu μ 的值,重新求解,这时可以允许解更加靠近(或到达)真正的最优边界。
  4. 多次迭代后, μ → 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+x321.

  • 可行域是单位球 { x ∈ R 3 : ∥ x ∥ ≤ 1 } \{x \in \mathbb{R}^3 : \|x\|\le 1 \} {xR3:x1}

  • 希望用内点法来解决不等式约束 x 1 2 + x 2 2 + x 3 2 ≤ 1 x_1^2 + x_2^2 + x_3^2 \le 1 x12+x22+x321
    通常在内点法中,会把不等式 (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+z21 )转写成形如 (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 μ(比如乘个衰减因子),让解逐步逼近约束边界并最终得到较准确的可行最优解。

在这份代码中:

  1. 外层循环 (共 max_outer 次):

    • 每次先用当前 μ \mu μ 在球内做若干步梯度下降,尝试求解 min ⁡ B ( x , μ ) \min B(x,\mu) minB(x,μ)
    • 之后衰减 μ \mu μ ← \leftarrow μ ⋅ \mu \cdot μ (mu_decay) \text{(mu\_decay)} (mu_decay),进入下一轮;
    • 重复,直到 μ \mu μ 足够小或者达到外层迭代上限。
  2. 内层循环 (共 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) xxαB(x,μ)
    • 如果发现新点 x new x_{\text{new}} xnew不可行(或者离边界过近),就缩小步长再试;
    • 如果两次迭代 ∥ x new − x ∥ \|x_{\text{new}} - x\| xnewx 非常小(< 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_outer
        for inner = 1:max_inner
            g = grad_B(x, mu);  
            x_new = x - alpha*g;

            % 若越过球边界 => h(x_new) <= 0
            if h_3d(x_new) <= 1e-9
                x_new = x - 0.1*alpha*g;  % 缩小步长再试
            end

            % 收敛判断
            if norm(x_new - x) < tol
                x = x_new;
                break;  % 跳出内层循环
            end

            x = x_new;
            x_history = [x_history; x']; 
        end

        % 减小 mu
        mu = mu * mu_decay;
        if mu < 1e-12
            break;    % mu 已经很小,不必再迭代
        end
    end

    % 加入最终点
    x_history = [x_history; x'];
end
  1. mu_init 设为 1.0,之后每次外层循环会 mu = mu * mu_decay,即乘以 0.2。这样大概迭代几次后就会让 mu 变得很小。
  2. alpha=0.001 是固定的梯度下降步长,相对比较小,所以我们用到 max_inner=50 步来让它收敛到一个合适精度。
  3. 收敛阈值 tol=1e-6:若相邻两步 ∥ x new − x ∥ \|x_{\text{new}}-x\| xnewx 小于这个值,就认为内层已经收敛。
  4. 每次更新 x 后都会把它记录到 x_history 里,用于可视化迭代轨迹。

这里值得注意的是:如果单纯用固定步长,可能碰到越过可行域边界(即 (x2+y2+z^2>1))的风险。为此,代码做了一个简单检查:

if h_3d(x_new) <= 1e-9
    x_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)=1r2,其中 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)1h(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))=1r22x.
带上负号“ − μ -\mu μ”一起,就得到对障碍项的贡献为 + 2 μ x 1 − r 2 +\frac{2\mu x}{1 - r^2} +1r22μ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)+1r22μ(x1,x2,x3).

在代码中,可以看到:

function g = grad_B(x, mu)
    hx = h_3d(x);  % 1 - r^2
    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

正好对应上面的公式:1.0 就是 ∇ f ( x ) \nabla f(x) f(x) 的那一部分, ( 2.0 ∗ m u ∗ x ( i ) / h x ) (2.0*mu*x(i)/hx) (2.0mux(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) (3 1,3 1,3 1)
因为在约束 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. 小结

  1. 内点法原理:通过把约束 x 1 2 + x 2 2 + x 3 2 ≤ 1 x_1^2 + x_2^2 + x_3^2 \le 1 x12+x22+x321 转化为对数障碍 − μ ln ⁡ ( 1 − r 2 ) -\mu \ln\bigl(1 - r^2\bigr) μln(1r2),并在外层迭代不断减小 μ \mu μ。这能保证迭代点始终在球内 ( h ( x ) > 0 h(x) > 0 h(x)>0),同时在 μ → 0 \mu\to0 μ0 时逐渐收敛到可行域边界上的最优点。

  2. 实现细节

    • 用固定步长 + 简单可行性校正(越界时缩步长);
    • max_outermax_inner 控制多重循环;
    • tol 判断迭代收敛;
    • 在每次迭代都记录 xx_history 中,用于可视化。
  3. 需要修正的地方
    代码中的 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) (3 1,3 1,3 1) 的迭代过程。


参考:为什么最优解是 ( − 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)。它的核心作用是:

  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))
    中,(\mu) 决定了 (-\mu \ln\bigl(h(x)\bigr)) 这部分惩罚力度的大小。

    • 当 (\mu) 较大时,对(\ln(h(x)))的惩罚力度相对较小,算法对靠近约束边界的“敏感度”不高,所以在收敛初期可以更自由地在可行域里移动。
    • 当 (\mu) 变小时,(-\mu \ln(h(x)))会变得更尖锐,迫使解更加贴近且“贴合”可行域的边界(若这是最优解所在的位置)。
  2. 帮助逐步逼近最优解并保持可行
    内点法的思路是:一开始用较大的 (\mu)(障碍作用较弱)来保证算法稳步地在可行域里进行搜索;之后在外层循环中逐步减小 (\mu),使对数障碍项逐渐变得陡峭,从而把解“推”到真正需要的边界附近并逼近最优解。

  3. 数值上的平衡

    • 如果 (\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_outer
        for inner = 1:max_inner
            g = 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-9
                x_new = x - 0.1*alpha*g;
            end

            % 收敛判断
            if norm(x_new - x) < tol
                x = x_new;
                break;
            end

            x = x_new;
            x_history = [x_history; x']; % 记录轨迹(行向量)
        end

        % 降低 mu 使解更逼近约束边界
        mu = mu * mu_decay;
        if mu < 1e-12
            break;
        end
    end

    % 最后再将最终点加入
    x_history = [x_history; x'];
end

%% 目标函数 f(x)
function val = f_3d(x)
    % f(x0, x1, x2) = x0 + x1 + x2
    val = 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 + x2
 subject 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视角


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/961460.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux下Ubuntun系统报错find_package(BLAS REQUIRED)找不到

Linux下Ubuntun系统报错find_package(BLAS REQUIRED)找不到 这次在windows的WSL2中遇到了一个非常奇怪的错误&#xff0c;就是 CMake Error at /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:230 (message):Could NOT find BLAS (missing: BLAS_LIBRAR…

Ubuntu Server 安装 XFCE4桌面

Ubuntu Server没有桌面环境&#xff0c;一些软件有桌面环境使用起来才更加方便&#xff0c;所以我尝试安装桌面环境。常用的桌面环境有&#xff1a;GNOME、KDE Plasma、XFCE4等。这里我选择安装XFCE4桌面环境&#xff0c;主要因为它是一个极轻量级的桌面环境&#xff0c;适合内…

芯片AI深度实战:实战篇之vim chat

利用vim-ollama这个vim插件&#xff0c;可以在vim内和本地大模型聊天。 系列文章&#xff1a; 芯片AI深度实战&#xff1a;基础篇之Ollama-CSDN博客 芯片AI深度实战&#xff1a;基础篇之langchain-CSDN博客 芯片AI深度实战&#xff1a;实战篇之vim chat-CSDN博客 芯片AI深度…

线程概念、操作

一、背景知识 1、地址空间进一步理解 在父子进程对同一变量进行修改时发生写时拷贝&#xff0c;这时候拷贝的基本单位是4KB&#xff0c;会将该变量所在的页框全拷贝一份&#xff0c;这是因为修改该变量很有可能会修改其周围的变量&#xff08;局部性原理&#xff09;&#xf…

设置jmeter外观颜色

设置jmeter外观颜色 方法&#xff1a; 步骤一、点击顶部选项 ->外观&#xff0c;这里提供了不同的主题&#xff0c;可选自己喜欢的风格。 步骤二、选择后&#xff0c;弹框提示点击Yes。

2021 年 6 月大学英语四级考试真题(第 1 套)——纯享题目版

&#x1f3e0;个人主页&#xff1a;fo安方的博客✨ &#x1f482;个人简历&#xff1a;大家好&#xff0c;我是fo安方&#xff0c;目前中南大学MBA在读&#xff0c;也考取过HCIE Cloud Computing、CCIE Security、PMP、CISP、RHCE、CCNP RS、PEST 3等证书。&#x1f433; &…

[论文总结] 深度学习在农业领域应用论文笔记14

当下&#xff0c;深度学习在农业领域的研究热度持续攀升&#xff0c;相关论文发表量呈现出迅猛增长的态势。但繁荣背后&#xff0c;质量却不尽人意。相当一部分论文内容空洞无物&#xff0c;缺乏能够落地转化的实际价值&#xff0c;“凑数” 的痕迹十分明显。在农业信息化领域的…

LangGraph系列-1:用LangGraph构建简单聊天机器人

在快速发展的人工智能和大型语言模型&#xff08;llm&#xff09;世界中&#xff0c;开发人员不断寻求创建更灵活、更强大、更直观的人工智能代理的方法。 虽然LangChain已经改变了这个领域的游戏规则&#xff0c;允许创建复杂的链和代理&#xff0c;但对代理运行时的更复杂控制…

【hot100】刷题记录(7)-除自身数组以外的乘积

题目描述&#xff1a; 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#x…

OpenCV边沿检测(Python版)

边缘检测是图像处理中的一项重要任务&#xff0c;用于找到图像中的边界或边缘。它在计算机视觉、图像处理和模式识别等领域中具有广泛的应用。 边缘可以被定义为图像亮度、颜色或纹理的突变区域。边缘检测算法旨在识别这些变化并将其标记为边缘。边缘检测可以用于分割图像、检测…

推荐七节来自NVIDIA、Google、斯坦福的AI课程

英伟达 &#xff08;1&#xff09;在 10 分钟内构建大脑 • 探索神经网络如何使用数据进行学习。 • 了解神经元背后的数学原理。 链接&#xff1a;https://learn.nvidia.com/courses/course-detail?course_idcourse-v1:DLIT-FX-01V1 &#xff08;2&#xff09;构建视频 A…

《从因果关系的角度学习失真不变表示以用于图像恢复》学习笔记

paper&#xff1a;2303.06859 GitHub&#xff1a;lixinustc/Causal-IR-DIL: Distortion invariant feature learning for image restoration from a causality perspective 2023 CVPR 摘要 近年来&#xff0c;我们见证了深度神经网络&#xff08;DNNs&#xff09;在图像恢复…

亚博microros小车-原生ubuntu支持系列:16 机器人状态估计

本来想测试下gmapping建图&#xff0c;但是底层依赖了yahboomcar_bringup做底层的数据处理&#xff0c;所以先把依赖的工程导入。 程序启动后&#xff0c;会订阅imu和odom数据&#xff0c;过滤掉一部分的imu数据后&#xff0c;然后与odom数据进行融合&#xff0c;最后输出一个…

不背单词快捷键(不背单词键盘快捷键)

文章目录 不背单词快捷键 不背单词快捷键 ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ        ‌‍ᅟᅠ    …

VPR概述、资源

SOTA网站&#xff1a; Visual Place Recognition | Papers With Code VPR&#xff08;Visual Place Recognition&#xff09; 是计算机视觉领域的一项关键任务&#xff0c;旨在通过图像匹配和分析来识别场景或位置。它的目标是根据视觉信息判断某个场景是否与数据库中的场景匹…

MYSQL 商城系统设计 商品数据表的设计 商品 商品类别 商品选项卡 多表查询

介绍 在开发商品模块时&#xff0c;通常使用分表的方式进行查询以及关联。在通过表连接的方式进行查询。每个商品都有不同的分类&#xff0c;每个不同分类下面都有商品规格可以选择&#xff0c;每个商品分类对应商品规格都有自己的价格和库存。在实际的开发中应该给这些表进行…

代理模式 -- 学习笔记

代理模式学习笔记 什么是代理&#xff1f; 代理是一种设计模式&#xff0c;用户可以通过代理操作&#xff0c;而真正去进行处理的是我们的目标对象&#xff0c;代理可以在方法增强&#xff08;如&#xff1a;记录日志&#xff0c;添加事务&#xff0c;监控等&#xff09; 拿一…

Flutter使用Flavor实现切换环境和多渠道打包

在Android开发中通常我们使用flavor进行多渠道打包&#xff0c;flutter开发中同样有这种方式&#xff0c;不过需要在原生中配置 具体方案其实flutter官网个了相关示例&#xff08;https://docs.flutter.dev/deployment/flavors&#xff09;,我这里记录一下自己的操作 Android …

WinDBG查找C++句柄泄露

C代码&#xff08;频繁点击About按钮导致Mutex句柄泄露&#xff09; HANDLE _mutexHandle;LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {switch (message){case WM_COMMAND:{int wmId LOWORD(wParam);// 分析菜单选择:switch (wmId){c…

Web3 如何赋能元宇宙,实现虚实融合的无缝对接

随着技术的飞速发展&#xff0c;元宇宙作为一个未来数字世界的概念&#xff0c;正在吸引全球范围内的关注。而 Web3 技术的兴起&#xff0c;为元宇宙的实现提供了强大的支撑。Web3 是基于区块链技术的去中心化网络&#xff0c;它在改变互联网的同时&#xff0c;也推动着虚拟世界…