最优化问题的外点罚函数法与内点罚函数法-MATLAB实现

一、算法原理概述

1.1 问题标准形式

min⁡x∈Rnf(x)s.t.gi(x)≤0,i=1,2,...,mhj(x)=0,j=1,2,...,p \begin{aligned} \min_{x \in \mathbb{R}^n} \quad & f(x) \\ \text{s.t.} \quad & g_i(x) \leq 0, \quad i=1,2,\dots,m \\ & h_j(x) = 0, \quad j=1,2,\dots,p \end{aligned} x∈Rnmins.t.f(x)gi(x)≤0,i=1,2,...,mhj(x)=0,j=1,2,...,p

1.2 外点罚函数法(External Penalty Method)

核心思想 :允许迭代点违反约束,对违反约束的解施加惩罚。

P(x,σ)=f(x)+σ∑i=1mmax⁡(0,gi(x))2+∑j=1phj(x)2 P(x, \sigma) = f(x) + \sigma \left \\sum_{i=1}\^m \\max(0,g_i(x))\^2 + \\sum_{j=1}\^p h_j(x)\^2 \\right P(x,σ)=f(x)+σi=1∑mmax(0,gi(x))2+j=1∑phj(x)2

  • σ\sigmaσ:惩罚因子,σ→+∞\sigma \to +\inftyσ→+∞ 迫使解趋近可行域
  • 初始点可在可行域外

1.3 内点罚函数法(Internal Penalty Method)

核心思想 :迭代点始终在可行域内,通过障碍函数阻止接近边界。

B(x,μ)=f(x)+μ∑i=1m1−gi(x)(倒数障碍) B(x, \mu) = f(x) + \mu \sum_{i=1}^m \frac{1}{-g_i(x)} \quad (\text{倒数障碍}) B(x,μ)=f(x)+μi=1∑m−gi(x)1(倒数障碍)

B(x,μ)=f(x)−μ∑i=1mln⁡(−gi(x))(对数障碍) B(x, \mu) = f(x) - \mu \sum_{i=1}^m \ln(-g_i(x)) \quad (\text{对数障碍}) B(x,μ)=f(x)−μi=1∑mln(−gi(x))(对数障碍)

  • μ\muμ:障碍参数,μ→0+\mu \to 0^+μ→0+ 迫使解趋近边界
  • 初始点必须在可行域内

二、MATLAB程序实现

2.1 主程序:penalty_methods_main.m

matlab 复制代码
%% 外点罚函数法与内点罚函数法求解最优化问题
clear; clc; close all;

%% 1. 定义优化问题
fprintf('=== 最优化问题的罚函数法求解 ===\n');

% 目标函数
f = @(x) x(1)^2 + x(2)^2;  % 最小化 x^2 + y^2

% 不等式约束 g(x) ≤ 0
g = @(x) [x(1) + x(2) - 1;   % g1: x + y - 1 ≤ 0
          -x(1);              % g2: -x ≤ 0
          -x(2)];             % g3: -y ≤ 0

% 等式约束 h(x) = 0
h = @(x) [];  % 无等式约束

% 理论最优解
x_opt_theoretical = [0.5, 0.5]';
f_opt_theoretical = f(x_opt_theoretical);

fprintf('目标函数: f(x) = x^2 + y^2\n');
fprintf('约束条件:\n');
fprintf('  g1: x + y - 1 ≤ 0\n');
fprintf('  g2: -x ≤ 0\n');
fprintf('  g3: -y ≤ 0\n');
fprintf('理论最优解: x* = [%.2f, %.2f]^T, f* = %.4f\n\n', ...
        x_opt_theoretical(1), x_opt_theoretical(2), f_opt_theoretical);

%% 2. 外点罚函数法
fprintf('--- 外点罚函数法 ---\n');
x0 = [2, 2]';  % 初始点(可行域外)
sigma0 = 1;    % 初始惩罚因子
sigma_inc = 10; % 惩罚因子增长倍数
max_iter = 50;
tol = 1e-6;

[x_ep, f_ep, history_ep] = exterior_penalty(f, g, h, x0, sigma0, sigma_inc, max_iter, tol);

%% 3. 内点罚函数法(对数障碍)
fprintf('\n--- 内点罚函数法(对数障碍) ---\n');
x0 = [0.6, 0.6]';  % 初始点(可行域内)
mu0 = 10;          % 初始障碍参数
mu_dec = 0.1;      % 障碍参数衰减倍数

[x_ip, f_ip, history_ip] = interior_penalty_log(f, g, h, x0, mu0, mu_dec, max_iter, tol);

%% 4. 结果对比与可视化
compare_results(f, g, x_ep, f_ep, x_ip, f_ip, history_ep, history_ip, x_opt_theoretical);

2.2 外点罚函数法实现

matlab 复制代码
function [x_opt, f_opt, history] = exterior_penalty(f, g, h, x0, sigma0, sigma_inc, max_iter, tol)
    % 外点罚函数法
    % f: 目标函数, g: 不等式约束, h: 等式约束
    % x0: 初始点, sigma0: 初始惩罚因子
    
    x = x0;
    sigma = sigma0;
    history.x = zeros(length(x0), max_iter);
    history.f = zeros(1, max_iter);
    history.penalty = zeros(1, max_iter);
    
    fprintf('迭代\t x1\t\t x2\t\t f(x)\t\t 惩罚项\t\t 罚因子\n');
    fprintf('%-4d\t %-8.4f %-8.4f %-10.4f %-10.4f %-10.2f\n', ...
            0, x(1), x(2), f(x), 0, sigma);
    
    for iter = 1:max_iter
        % 构造增广目标函数
        P = @(x) augmented_objective_exterior(f, g, h, x, sigma);
        
        % 无约束优化(使用fminunc)
        options = optimoptions('fminunc', 'Algorithm', 'quasi-newton', ...
                              'Display', 'off', 'MaxIter', 100);
        x_new = fminunc(P, x, options);
        
        % 计算约束违反度
        constraint_violation = constraint_violation_norm(g, h, x_new);
        
        % 记录历史
        history.x(:,iter) = x_new;
        history.f(iter) = f(x_new);
        history.penalty(iter) = penalty_term_exterior(g, h, x_new, sigma);
        
        fprintf('%-4d\t %-8.4f %-8.4f %-10.4f %-10.4f %-10.2f\n', ...
                iter, x_new(1), x_new(2), f(x_new), constraint_violation, sigma);
        
        % 收敛检查
        if constraint_violation < tol && norm(x_new - x) < tol
            fprintf('收敛于第 %d 次迭代\n', iter);
            break;
        end
        
        % 更新
        x = x_new;
        sigma = sigma * sigma_inc;  % 增大惩罚因子
    end
    
    x_opt = x;
    f_opt = f(x_opt);
end

function P = augmented_objective_exterior(f, g, h, x, sigma)
    % 外点罚函数增广目标
    P = f(x);
    
    % 不等式约束惩罚(二次惩罚)
    m = length(g(x));
    for i = 1:m
        P = P + sigma * max(0, g(x)(i))^2;
    end
    
    % 等式约束惩罚(二次惩罚)
    p = length(h(x));
    for j = 1:p
        P = P + sigma * h(x)(j)^2;
    end
end

function penalty = penalty_term_exterior(g, h, x, sigma)
    penalty = 0;
    m = length(g(x));
    for i = 1:m
        penalty = penalty + sigma * max(0, g(x)(i))^2;
    end
    p = length(h(x));
    for j = 1:p
        penalty = penalty + sigma * h(x)(j)^2;
    end
end

2.3 内点罚函数法(对数障碍)实现

matlab 复制代码
function [x_opt, f_opt, history] = interior_penalty_log(f, g, h, x0, mu0, mu_dec, max_iter, tol)
    % 内点罚函数法(对数障碍)
    % f: 目标函数, g: 不等式约束, h: 等式约束
    % x0: 初始点(必须在可行域内), mu0: 初始障碍参数
    
    x = x0;
    mu = mu0;
    history.x = zeros(length(x0), max_iter);
    history.f = zeros(1, max_iter);
    history.barrier = zeros(1, max_iter);
    
    fprintf('迭代\t x1\t\t x2\t\t f(x)\t\t 障碍项\t\t 障碍参数\n');
    fprintf('%-4d\t %-8.4f %-8.4f %-10.4f %-10.4f %-10.4f\n', ...
            0, x(1), x(2), f(x), 0, mu);
    
    for iter = 1:max_iter
        % 构造增广目标函数(对数障碍)
        B = @(x) barrier_objective_log(f, g, h, x, mu);
        
        % 无约束优化
        options = optimoptions('fminunc', 'Algorithm', 'quasi-newton', ...
                              'Display', 'off', 'MaxIter', 100);
        x_new = fminunc(B, x, options);
        
        % 检查可行性
        if any(g(x_new) >= 0)
            warning('迭代点超出可行域!');
            break;
        end
        
        % 计算障碍项值
        barrier_value = barrier_term_log(g, x_new, mu);
        
        % 记录历史
        history.x(:,iter) = x_new;
        history.f(iter) = f(x_new);
        history.barrier(iter) = barrier_value;
        
        fprintf('%-4d\t %-8.4f %-8.4f %-10.4f %-10.4f %-10.4f\n', ...
                iter, x_new(1), x_new(2), f(x_new), barrier_value, mu);
        
        % 收敛检查
        if norm(x_new - x) < tol && barrier_value < tol
            fprintf('收敛于第 %d 次迭代\n', iter);
            break;
        end
        
        % 更新
        x = x_new;
        mu = mu * mu_dec;  % 减小障碍参数
    end
    
    x_opt = x;
    f_opt = f(x_opt);
end

function B = barrier_objective_log(f, g, h, x, mu)
    % 对数障碍函数
    B = f(x);
    
    % 不等式约束障碍项
    m = length(g(x));
    for i = 1:m
        if g(x)(i) >= 0
            B = B + 1e10;  % 不可行点给予极大惩罚
        else
            B = B - mu * log(-g(x)(i));
        end
    end
    
    % 等式约束处理(内点法通常不直接处理等式约束,需特殊处理)
    p = length(h(x));
    for j = 1:p
        B = B + mu * h(x)(j)^2;  % 等式约束用二次惩罚
    end
end

function barrier = barrier_term_log(g, x, mu)
    barrier = 0;
    m = length(g(x));
    for i = 1:m
        barrier = barrier - mu * log(-g(x)(i));
    end
end

2.4 辅助函数

matlab 复制代码
function violation = constraint_violation_norm(g, h, x)
    % 计算约束违反度
    violation = 0;
    
    % 不等式约束
    m = length(g(x));
    for i = 1:m
        violation = violation + max(0, g(x)(i))^2;
    end
    
    % 等式约束
    p = length(h(x));
    for j = 1:p
        violation = violation + h(x)(j)^2;
    end
    
    violation = sqrt(violation);
end

function compare_results(f, g, x_ep, f_ep, x_ip, f_ip, history_ep, history_ip, x_opt)
    % 结果对比与可视化
    
    fprintf('\n=== 结果对比 ===\n');
    fprintf('理论最优解: x* = [%.4f, %.4f]^T, f* = %.4f\n', x_opt(1), x_opt(2), f(x_opt));
    fprintf('外点法结果: x = [%.4f, %.4f]^T, f = %.4f\n', x_ep(1), x_ep(2), f_ep);
    fprintf('内点法结果: x = [%.4f, %.4f]^T, f = %.4f\n', x_ip(1), x_ip(2), f_ip);
    
    % 可视化
    figure('Position', [100, 100, 1200, 400]);
    
    % 1. 可行域与迭代路径
    subplot(1,3,1);
    plot_feasible_region(g, x_opt);
    hold on;
    plot(history_ep.x(1,:), history_ep.x(2,:), 'ro-', 'LineWidth', 1.5, 'MarkerSize', 6);
    plot(history_ip.x(1,:), history_ip.x(2,:), 'bs-', 'LineWidth', 1.5, 'MarkerSize', 6);
    plot(x_opt(1), x_opt(2), 'kp', 'MarkerSize', 15, 'LineWidth', 2);
    xlabel('x_1'); ylabel('x_2');
    title('可行域与迭代路径');
    legend('可行域', '外点法', '内点法', '理论最优', 'Location', 'northwest');
    grid on; axis equal;
    
    % 2. 目标函数值收敛
    subplot(1,3,2);
    plot(0:length(history_ep.f)-1, history_ep.f, 'r-o', 'LineWidth', 2, 'MarkerSize', 6);
    hold on;
    plot(0:length(history_ip.f)-1, history_ip.f, 'b-s', 'LineWidth', 2, 'MarkerSize', 6);
    plot([0, max(length(history_ep.f), length(history_ip.f))], [f(x_opt), f(x_opt)], 'k--', 'LineWidth', 1.5);
    xlabel('迭代次数'); ylabel('目标函数值');
    title('目标函数值收敛');
    legend('外点法', '内点法', '理论最优', 'Location', 'northwest');
    grid on;
    
    % 3. 惩罚/障碍项变化
    subplot(1,3,3);
    yyaxis left;
    plot(0:length(history_ep.penalty)-1, history_ep.penalty, 'r-o', 'LineWidth', 2);
    ylabel('外点惩罚项');
    
    yyaxis right;
    plot(0:length(history_ip.barrier)-1, history_ip.barrier, 'b-s', 'LineWidth', 2);
    ylabel('内点障碍项');
    
    xlabel('迭代次数');
    title('惩罚/障碍项变化');
    grid on;
end

function plot_feasible_region(g, x_opt)
    % 绘制可行域
    x1 = linspace(0, 1.5, 100);
    x2 = linspace(0, 1.5, 100);
    [X1, X2] = meshgrid(x1, x2);
    
    % 计算约束值
    G = zeros(size(X1));
    for i = 1:size(X1,1)
        for j = 1:size(X1,2)
            G(i,j) = g([X1(i,j); X2(i,j)])(1);  % g1: x+y-1
        end
    end
    
    % 绘制可行域
    contourf(X1, X2, G, [0, 0], 'FaceColor', [0.9, 0.9, 0.9], 'EdgeColor', 'none');
    hold on;
    
    % 绘制约束边界
    plot([0, 1], [1, 0], 'k--', 'LineWidth', 1.5);  % x+y=1
    plot([0, 0], [0, 1.5], 'k--', 'LineWidth', 1.5);  % x=0
    plot([0, 1.5], [0, 0], 'k--', 'LineWidth', 1.5);  % y=0
end

三、算法特性对比

特性 外点罚函数法 内点罚函数法
初始点要求 可在可行域外 必须在可行域内
约束处理 允许违反约束 严格禁止违反
惩罚参数 递增(σ→∞\sigma \to \inftyσ→∞) 递减(μ→0\mu \to 0μ→0)
数值稳定性 可能产生病态问题 相对稳定
收敛性 全局收敛性好 可能收敛到局部最优
适用场景 一般约束优化 不等式约束为主

四、使用示例(自定义问题)

4.1 带等式约束的问题

matlab 复制代码
% 修改目标函数和约束
f = @(x) (x(1)-2)^2 + (x(2)-1)^2;
g = @(x) [x(1)^2 + x(2)^2 - 4];  % 圆内
h = @(x) x(1) + x(2) - 2;        % 直线

x0_ep = [0, 0]';   % 可行域外
x0_ip = [0.5, 0.5]'; % 可行域内

[x_ep, f_ep] = exterior_penalty(f, g, h, x0_ep, 1, 10, 50, 1e-6);
[x_ip, f_ip] = interior_penalty_log(f, g, h, x0_ip, 10, 0.1, 50, 1e-6);

4.2 高维问题(三维)

matlab 复制代码
% 三维优化问题
f = @(x) x(1)^2 + 2*x(2)^2 + 3*x(3)^2;
g = @(x) [x(1) + x(2) + x(3) - 1;
          -x(1); -x(2); -x(3)];

x0 = [0.5, 0.3, 0.2]';
[x_opt, f_opt] = interior_penalty_log(f, g, @(x)[], x0, 10, 0.1, 100, 1e-6);

参考代码 求解最优化问题的外点罚函数法、内点罚函数法的matlab程序 www.youwenfan.com/contentcsv/79349.html

五、注意事项与改进建议

5.1 常见问题解决

问题 解决方案
收敛慢 调整惩罚因子增长/衰减速率
数值不稳定 使用对数障碍代替倒数障碍
初始点敏感 尝试多个不同初始点
等式约束难处理 将等式约束转化为两个不等式

5.2 工程优化建议

matlab 复制代码
% 1. 自适应惩罚因子调整
if constraint_violation > prev_violation
    sigma = sigma * 20;  % 违反度增加时加大惩罚
end

% 2. 混合策略(外点+内点)
% 先用外点法快速接近可行域,再用内点法精细搜索

% 3. 多起点策略
% 从不同初始点运行,选择最优结果

六、总结

本MATLAB程序完整实现了:

  1. 外点罚函数法:允许迭代点在可行域外,通过递增惩罚因子迫使解趋近可行域
  2. 内点罚函数法:迭代点始终在可行域内,通过递减障碍参数迫使解趋近边界
  3. 完整的可视化:迭代路径、收敛曲线、惩罚项变化
  4. 灵活的问题定义:支持自定义目标函数、不等式和等式约束

关键优势

  • 算法原理清晰,代码模块化
  • 支持任意维度的优化问题
  • 完整的收敛性检查和结果分析
  • 可直接应用于工程实际问题
相关推荐
弹简特1 小时前
【零基础学Python】05-Python函数完全指南:从初阶定义到进阶参数,一篇打通核心难点
开发语言·python
AugustRed1 小时前
A2UI 完整学习指南(含 Java 后端 + 前端实战示例)
java·开发语言·前端
jghhh011 小时前
MATLAB蒙特卡罗方法求解伊辛模型
数据库·人工智能·matlab
jingling5551 小时前
自建技术博客实战(三):工具专栏——地图定位、声音复刻与 rembg 抠图
android·开发语言·前端·ai·nextjs
basketball6161 小时前
C++进阶:1. 引用折叠规则
java·开发语言·c++
Deep-w2 小时前
【MATLAB】基于模型预测控制的自适应巡航车辆过渡工况安全控制研究
开发语言·人工智能·算法·机器学习·matlab
Java_2017_csdn2 小时前
Java 策略模式(Strategy Pattern)-(三)
java·开发语言·servlet
许彰午2 小时前
06_Java面向对象入门
java·开发语言·python
Java_2017_csdn2 小时前
Java 策略模式(Strategy Pattern)-(二)
java·开发语言·策略模式