非线性约束的优化问题_序列二次规划算法代码

1. 理论部分

2. 序列二次规划算法代码及解析

3.完整代码

1.理论部分

a.约束优化问题的极值条件

库恩塔克条件(Kuhn-Tucker conditions,KT条件)是确定某点为极值点的必要条件。如果所讨论的规划是凸规划,那么库恩-塔克条件也是充分条件。

(1)判断数值x处起作用的约束,计算x处各约束的取值是否为0,找出起作用的约束条件。并非所有约束条件都起作用,即并非落在所有约束条件的边界交集处。对于起作用的边界条件,满足边界函数g(x)或h(x)为0;

(2)数值x处,目标函数导数f'(x)和起作用的约束导数g'(x)的数值;

(3)代入KT条件(ex. f'(x) + \lambda_1 g'(x_1) + \lambda_2 g'(x_2) =0),求解拉格朗日乘子λ的大小,判断λ是否大于0,若大于零,则为极值点。

(4)若不满足条件,继续迭代。

具体做法如下:

其中λ为拉格朗日乘子,当某一点x使λ > 0存在时,称满足KT条件,则该点x是极值点。
约束优化问题的应用示例如下图:

b.约束优化方法及迭代
此处介绍和使用外惩罚函数法/外点法

外点法是一种从随机一点(一般在可行域外)出发,逐渐移动到可行区域的方法。
对于约束优化问题:

\min_{x}f(x)

s.t. \space g_u(x) \leqslant 0, \space u=1,2,...m

s.t. \space h_v(x) = 0, \space v=1,2,...p

构造外惩罚函数:

\Phi(x, M_k) = f(x) + M_k \left \{ \sum_{u=1}^{m} (max[g_u(x),0])^2 + \sum_{v=1}^{p} (h_v(x))^2 \right \}

即,当g(x)不满足条件时,该项有大于0的值,h(x)不满足条件时,该项也有值,加和的越大代表该数值点距离距离约束的可行域越远,惩罚项的值越大,惩罚作用越明显。。其中Mk为外罚因子,M 0 < M 1 < M 2 . . . < M k 为递增的正数序列,一般M0=1,递增系数c=5~8。

迭代终止满足两个判断条件中一个即可:

1. Q\leqslant 10^{-3},Q为当前数值点多个约束函数中最大的值,即满足了所有的约束函数条件。

2. M> R 且 \left \| xM_{k+1} - xM_k \right \| \leqslant \epsilon,R为外罚因子控制量,M超出外罚因子的极限R

外点法的迭代图如下:

外点法的示例如下图:

a. 定义变量

vars = 2; % 自变量数量
cons = 1; % 约束数量
maxIter=100; % 最大迭代次数
x = [-1;4]; % 初始猜测值
l =0; % 拉格朗日乘子
H = eye(vars,vars); % Hessian 矩阵,假设为I矩阵

目标函数为

f(x)= x_1^4 - 2x_1^2x_2+x_2^2+x_1^2-2x_1+5

及目标函数的导数为

f'(x_1) = 4x_1^3 - 4x_1x_2 + 2x_1 - 2

f'(x_2) = -2x_1^2 + 2x_2

function y = f(x)
    y = x(1)^4 - 2*x(2)*x(1)^2 + x(2)^2 + x(1)^2 - 2*x(1)+5;
end

function y = gradf(x)
    y(1) = 2*x(1)-4*x(1)*x(2)+4*x(1)^3-2;
    y(2) = -2*x(1)^2 + 2*x(2);
end

约束项不等式为

-(x_1 + 0.25)^2 + 0.75x_2 >= 0

以及其导数为

g'(x_1) = -2(x_1 -0.25)=-2x_1-0.5

g'(x_2) = 0.75

function y = g(x)
    y(1) = -(x(1)+0.25)^2+0.75*x(2);
end

function y = gradg(x)
    y(1,1) = -2*x(1)-1/2;
    y(1,2) = 3/4;
end

求解KKT条件

function y = SolveKKT(gradfEval,gradgEval,gEval,Hessian)
    A = [Hessian -gradgEval';gradgEval 0]; %对称矩阵,约束函数的梯度矩阵
    b = [-gradfEval -gEval]';
    y = A\b; %方程  Ay = b 解出y值,分别对应最优的x值的梯度和最优的拉格朗日乘子的值
    %即此时Ay-b = 0,kkt条件成立,
end

判断数值点x是否满足约束条件

function [gViol,lViol] = Viols(gEval,l)%约束条件函数值,拉格朗日乘子l
    gViol=[];
    lViol=[];
    for i = 1:length(gEval)
        if gEval(i)<0  %如果约束条件函数值小于零,即,不满足约束条件
            gViol(i)=gEval(i); %将约束条件函数值和拉格朗日乘子l,放入列表
            lViol(i)=l(i);
        end    
    end
end

处理不满足约束的情况,构造惩罚函数,lViol对应Mk,累加得到惩罚函数

function y = Penalty(fEval,gViol,lViol)
%代入该点处的函数值,不满足约束的约束函数值,以及拉格朗日乘子l
    sum = 0;
    y = fEval;
    for i = 1:length(gViol) %找出不满足约束条件的约束函数值
        sum = sum +  lViol(i)*abs(gViol(i)); %约束函数值g(x)求反,再乘一个系数,即,||l_1*g(x1)+l2*g(x2) ||
    end
    y = y + sum;
end

在初始点首先进行初始计算,找出不满足约束的约束,计算其损失函数。

% EVALUATE AT STARTING POINT

fEval= f(x);
gEval = g(x);
[gViol,lViol] = Viols(gEval,l); 
gradfEval = gradf(x);
gradgEval = gradg(x);
P = Penalty(fEval,gViol,lViol);

开始进入SQP算法主体,求解kkt条件,得到xSol为函数x的解,lSol为拉格朗日乘子的解。

for i=1:maxIter %开始循环迭代

    % SOLVE KKT CONDITIONS FOR THE OPTIMUM OF THE QUADRATIC APPROXIMATION
    %求解二次优化的KKT条件
    sol = SolveKKT(gradfEval,gradgEval,gEval,H);%代入导数f'(x),g'(x),约束函数值g(x),Hessian矩阵,
    xSol = sol(1:vars);
    lSol = sol(vars+1:vars+cons);

如果拉格朗日乘子有负的,即,不满足约束条件,则将其设为0,并重新求解方程\frac{\partial {f_(x^*)}^2 }{\partial x^2} {sol}= f'(x^*)

    for j = 1:length(lSol)
        if lSol(j)<0    %如果拉格朗日乘子有一个是负的
            sol= H\(-gradfEval)'; %将结果重新求解H*x = -gradfEval
            xSol = sol(1:vars);
            lSol(j)=0;  %该约束的拉格朗日乘子置为0
        end
    end

计算新的数值点情况

    xNew = x + xSol; %更新得到新的数值点
    lNew = lSol;  % 得到新的拉格朗日乘子
    fEvalNew = f(xNew);%计算新点目标函数的数值
    gEvalNew = g(xNew);%计算新点的约束函数数值
    gradfEvalNew = gradf(xNew);%计算该点目标函数梯度
    gradgEvalNew = gradg(xNew);%计算该点约束函数梯度
    [gViolNew,lViolNew] = Viols(gEvalNew,lNew);%找出不满足的约束条件
    PNew = Penalty(fEvalNew,gViolNew,lViolNew);%求解惩罚函数

如果惩罚函数增加,减小步长到原来的一半

    % IF PENALTY FUNCTION INCREASED, LOWER THE STEP BY 0.5
    
    while PNew-P>1e-4
        xSol = 0.5*xSol;
        xNew = x + xSol;
        fEvalNew = f(xNew);
        gEvalNew = g(xNew);
        gradfEvalNew = gradf(xNew);
        gradgEvalNew = gradg(xNew);
        [gViolNew,lViolNew] = Viols(gEvalNew,lNew);
        PNew = Penalty(fEvalNew,gViolNew,lViolNew);
    end

如果x数值变化很小,停止迭代,找到最优,结束迭代

    % STOPPING CRITERION
    
    if norm(xNew(1:vars)-x(1:vars))<=1e-2
        break
    end

更新Hessian矩阵,Q为Mk+1- Mk的值

    % UPDATE THE HESSIAN
    
    gradLEval = gradLagr(gradfEval,gradgEval,lNew,vars); 
    %拉格朗日函数的梯度 lnew not l!!!
    gradLEvalNew = gradLagr(gradfEvalNew,gradgEvalNew,lNew,vars);
    %新的数值点处,拉格朗日函数的梯度
    Q = gradLEvalNew-gradLEval;
    %拉格朗日函数数值的差分L(x_k+1) - L(x_k)
    dx = xNew-x;
    %自变量x的差分
    HNew = UpdateH(H,dx,Q);%求解H矩阵

计算拉格朗日乘子梯度的函数

function y = gradLagr(gradfEval,gradgEval,l,n)
    y = gradfEval';
    sum = zeros(n,1);
        for i = 1:length(l)
            sum = sum -l(i)*gradgEval(i:n)';
        end
    y = y + sum;  %x处目标函数的梯度,减去约束函数的梯度。即,拉格朗日函数的梯度
end

更新Hessian矩阵,gamma为Mk+1- Mk的值

function y = UpdateH(H,dx,gamma)%gamma是拉格朗日函数的两次差分
    term1=(gamma*gamma') / (gamma'*dx);
    term2 = ((H*dx)*(dx'*H)) / (dx'*(H*dx));
    y = H + term1-term2; %更新得到新的H矩阵
end

更新所有的变量,用于下次的迭代,包括Hessian矩阵H,数值点x,惩罚函数值P,目标函数值fEval,目标函数值梯度gradEval,约束函数值gEval,约束函数值梯度gradgEval

    % UPDATE ALL VALUES FOR NEXT ITERATION
    
    H = HNew;
    fEval = fEvalNew;
    gEval = gEvalNew;
    gradfEval = gradfEvalNew;
    gradgEval = gradgEvalNew;
    P = PNew;
    x = xNew;

3.可以运行的完整代码如下:

% EXAMPLE OF SQP ALGORITHM

clear variables; close all; clc;
fprintf("---------------------------------------------------------------\n")
fprintf("An implementation of Sequential Quadratic Programming method\nin a nonlinear constrained optimization problem\n")
fprintf("---------------------------------------------------------------\n")

% INITIAL VALUES - INPUT

vars = 2; % number of variables
cons = 1; % number of constraints
maxIter=100; % max iterations
x = [-1;4]; % initial guess point
l =0; % LagrangeMultipliers vector
H = eye(vars,vars); % Hessian matrix assumed to be identity

% EVALUATE AT STARTING POINT

fEval= f(x);
gEval = g(x);
[gViol,lViol] = Viols(gEval,l); 
gradfEval = gradf(x);
gradgEval = gradg(x);
P = Penalty(fEval,gViol,lViol);

% SQP ALGORITHM

for i=1:maxIter

    % SOLVE KKT CONDITIONS FOR THE OPTIMUM OF THE QUADRATIC APPROXIMATION
    
    sol = SolveKKT(gradfEval,gradgEval,gEval,H);
    xSol = sol(1:vars);
    lSol = sol(vars+1:vars+cons);
    
    % IF THE LAGRANGE MULTIPLIER IS NEGATIVE SET IT TO ZERO
    
    for j = 1:length(lSol)
        if lSol(j)<0 
            sol= H\(-gradfEval)';
            xSol = sol(1:vars);
            lSol(j)=0;
        end
    end
    
    % EVALUATE AT NEW CANDIDATE POINT
    
    xNew = x + xSol; 
    lNew = lSol;
    fEvalNew = f(xNew);
    gEvalNew = g(xNew);
    gradfEvalNew = gradf(xNew);
    gradgEvalNew = gradg(xNew);
    [gViolNew,lViolNew] = Viols(gEvalNew,lNew);
    PNew = Penalty(fEvalNew,gViolNew,lViolNew);
    
    % IF PENALTY FUNCTION INCREASED, LOWER THE STEP BY 0.5
    
    while PNew-P>1e-4
        xSol = 0.5*xSol;
        xNew = x + xSol;
        fEvalNew = f(xNew);
        gEvalNew = g(xNew);
        gradfEvalNew = gradf(xNew);
        gradgEvalNew = gradg(xNew);
        [gViolNew,lViolNew] = Viols(gEvalNew,lNew);
        PNew = Penalty(fEvalNew,gViolNew,lViolNew);
    end
    
    % STOPPING CRITERION
    
    if norm(xNew(1:vars)-x(1:vars))<=1e-2
        break
    end
    
    % UPDATE THE HESSIAN
    
    gradLEval = gradLagr(gradfEval,gradgEval,lNew,vars); % lnew not l!!!
    gradLEvalNew = gradLagr(gradfEvalNew,gradgEvalNew,lNew,vars);
    Q = gradLEvalNew-gradLEval;
    dx = xNew-x;
    HNew = UpdateH(H,dx,Q);
    
    % UPDATE ALL VALUES FOR NEXT ITERATION
    
    H = HNew;
    fEval = fEvalNew;
    gEval = gEvalNew;
    gradfEval = gradfEvalNew;
    gradgEval = gradgEvalNew;
    P = PNew;
    x = xNew;
end

fprintf('SQP: Optimum point:\n x1=%10.4f\n x2=%10.4f\n iterations =%10.0f \n', x(1), x(2), i)

% FUNCTIONS NEEDED

function y = SolveKKT(gradfEval,gradgEval,gEval,Hessian)
    A = [Hessian -gradgEval';gradgEval 0];
    b = [-gradfEval -gEval]';
    y = A\b;
end

function y = f(x)
    y = x(1)^4 - 2*x(2)*x(1)^2 + x(2)^2 + x(1)^2 - 2*x(1)+5;
end

function y = gradf(x)
    y(1) = 2*x(1)-4*x(1)*x(2)+4*x(1)^3-2;
    y(2) = -2*x(1)^2 + 2*x(2);
end

function y = gradLagr(gradfEval,gradgEval,l,n)
    y = gradfEval';
    sum = zeros(n,1);
        for i = 1:length(l)
            sum = sum -l(i)*gradgEval(i:n)';
        end
    y = y + sum;
end


function y = gradg(x)
    y(1,1) = -2*x(1)-1/2;
    y(1,2) = 3/4;
end

function y = g(x)
    y(1) = -(x(1)+0.25)^2+0.75*x(2);
end

function [gViol,lViol] = Viols(gEval,l)
    gViol=[];
    lViol=[];
    for i = 1:length(gEval)
        if gEval(i)<0
            gViol(i)=gEval(i);
            lViol(i)=l(i);
        end    
    end
end


function y = Penalty(fEval,gViol,lViol)
    sum = 0;
    y = fEval;
    for i = 1:length(gViol)
        sum = sum +  lViol(i)*abs(gViol(i));
    end
    y = y + sum;
end

function y = UpdateH(H,dx,gamma)
    term1=(gamma*gamma') / (gamma'*dx);
    term2 = ((H*dx)*(dx'*H)) / (dx'*(H*dx));
    y = H + term1-term2;
end

最后输出结果为:

---------------------------------------------------------------
An implementation of Sequential Quadratic Programming method
in a nonlinear constrained optimization problem
---------------------------------------------------------------
SQP: Optimum point:
 x1=    0.4999
 x2=    0.7498
 iterations =         9 

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

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

相关文章

5.OpenResty系列之深入理解(一)

本文基于Centos8进行实践&#xff0c;请读者自行安装OpenResty。 1. 内部调用 进入默认安装路径 cd /usr/local/openresty/nginx/conf vim nginx.conflocation /sum {# 只允许内部调用internal;content_by_lua_block {local args ngx.req.get_uri_args()ngx.print(tonumber…

Qt 多线程用法

文章目录 开发平台QThread 类 moveToThreadQtConcurrent::run QFutureWatcherQThreadPool QRunnable 开发平台 项目说明OSwin10 x64Qt6.6compilermsvc2022构建工具cmake QThread 类 moveToThread 写一个简单的例子吧,比较容易理解,方便入门. 也可以看出这种方式,对于线程…

服务器IBM x3650 m2 管理口访问故障处理

服务器的内存告警后&#xff0c;连接管理口查看信息&#xff0c;管理口状态灯显示正常&#xff0c;但是无法ping通和访问。 处理过程如下&#xff1a; 1、在centos 6.6中安装ipmitool&#xff0c;替换为阿里云的yum源&#xff0c;然后安装。 # wget -O /etc/yum.repos.d/Cen…

Unity自带的NavMesh寻路组件

最近看了一下Unity自带的NavMesh寻路组件&#xff0c;先说一下基本的使用&#xff1a; 首先先把AI Navgation的package包给安装上。 给场景地图添加上NavMeshSurface组件&#xff0c;然后进行烘焙&#xff0c;烘焙出对应的场景地图文件。 给移动物体添加对应的Nav MeshAgent组…

【雷达原理】雷达测速原理及实现方法

一、雷达测速原理 1.1 多普勒频率 当目标和雷达之间存在相对运动时&#xff0c;若雷达发射信号的工作频率为&#xff0c;则接收信号的频率为&#xff0c;其中为多普勒频率。将这种由于目标相对于辐射源运动而导致回波信号的频率发生变化的现象称为多普勒效应。 如图1-1所示&a…

FATFS文件系统

文件系统是为了存储和管理数据&#xff0c;而在存储设备上建立的一种组织结构。 Windows常用的文件系统&#xff1a; 1、FAT12 2、FAT16 3、FAT32 4、exFAT 5、NTFS FAT&#xff1a;File Alloction Table 文件分配表 在小型的嵌入式存储设备大多…

Bwapp学习笔记

1.基本sql语句 #求绝对值 select abs(-1) from dual; #取余数 select mod(10,3); #验证show databases结果是取之于schemata表的 show databases; select schema_name from information_schema.schemata; #查询当前的数据库 select database(); -- 查询数据库版本 s…

Java研学-Servlet 基础

一 概述 1 介绍 Servlet&#xff08;Server Applet&#xff09;是Java Servlet的简称&#xff0c;称为小服务程序或服务连接器&#xff0c;用Java编写的服务器端程序&#xff0c;具有独立于平台和协议的特性&#xff0c;主要功能在于交互式地浏览和生成数据&#xff0c;生成动…

【数据结构】什么是树?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;树的定义 &#x1f4cc;树的相关概念 &#x1f4cc;线性结构与树结构的对比 &#x1f4cc;树的抽象数据类型 &#x1f4cc;树的存储结构 &#x1f38…

叮咚,微信年度聊天报告(圣诞节版)请查收~丨GitHub star 16.8k+

微信年度聊天报告——圣诞节特别版&#xff0c;快发给心仪的ta吧~ 开源地址 GitHub开源地址&#xff1a;https://github.com/LC044/WeChatMsg 我深信有意义的不是微信&#xff0c;而是隐藏在对话框背后的一个个深刻故事。未来&#xff0c;每个人都能拥有AI的陪伴&#xff0c;…

Docker - 镜像 | 容器 日常开发常用指令 + 演示(一文通关)

目录 Docker 开发常用指令汇总 辅助命令 docker version docker info docker --help 镜像命令 查看镜像信息 下载镜像 搜索镜像 删除镜像 容器命令 查看运行中的容器 运行容器 停止、启动、重启、暂停、恢复容器 杀死容器 删除容器 查看容器日志 进入容器内部…

2024年【北京市安全员-B证】考试题库及北京市安全员-B证模拟试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【北京市安全员-B证】考试题库及北京市安全员-B证模拟试题&#xff0c;包含北京市安全员-B证考试题库答案和解析及北京市安全员-B证模拟试题练习。安全生产模拟考试一点通结合国家北京市安全员-B证考试最新大纲…

直接插入排序【从0-1学数据结构】

文章目录 &#x1f497; 直接插入排序Java代码C代码JavaScript代码稳定性时间复杂度空间复杂度 我们先来学习 直接插入排序, 直接排序算是所有排序中最简单的了,代码也非常好实现,尽管直接插入排序很简单,但是我们依旧不可以上来就直接写代码,一定要分析之后才开始写,这样可以提…

手写线程池

手写线程池 线程池原理 线程池的组成主要分为3个部分&#xff0c;这三部分配合工作就可以得到一个完整的线程池&#xff1a; 任务队列&#xff0c;存储需要处理的任务&#xff0c;由工作的线程来处理这些任务 通过线程池提供的API函数&#xff0c;将一个待处理的任务添加到任…

从归并排序引申到排序链表-图解

从归并排序引申到排序链表 文章目录 从归并排序引申到排序链表归并排序递归版非递归版 排序链表递归版非递归版 归并排序 递归版 //合并排序public static void mergeSort(int[] nums) {mergeSortHelper(0, nums.length, nums); //没有-1}private static void mergeSortHelper…

python 使用 pip 安装第三方库 导入不成功

本文是什么意思呢&#xff1f; 就是你需要使用一些库安装老师或者网上说的 通过pip 安装下载了第三方库&#xff0c;但是使用 import xxx from xxx import xx &#xff0c;pycharm ide 导入的下面还有红色波浪线&#xff0c;导入不成功。 这是什么原因&#xff1f; 这是pyc…

飞天使-k8s知识点5-kubernetes基础名词扫盲

文章目录 deploymentspodNodeserviceskubectl 实现应用伸缩kubectl 实现滚动更新kubernetes架构 deployments 中文文档 http://docs.kubernetes.org.cn/251.htmldeployment是用来创建和更新应用的&#xff0c;master 会负责将创建好的应用实例调度到集群中的各个节点 应用实例…

Qt 开源项目

Qt 开源项目 Omniverse View链接技术介绍 QuickQanava链接技术介绍QField链接技术介绍 AtomicDEX链接技术介绍 Status-desktop链接技术介绍 Librum链接技术介绍 A Simple Cross-Platform ReaderQPrompt链接技术介绍 GCompris链接技术介绍 Scrite链接技术介绍 QSkinny链接技术介…

力扣思维题——寻找重复数

题目链接&#xff1a;https://leetcode.cn/problems/find-the-duplicate-number/description/?envTypestudy-plan-v2&envIdtop-100-liked 这题的思维难度较大。一种是利用双指针法进行计算环的起点&#xff0c;这种方法在面试里很难说清楚&#xff0c;也很难想到。大致做…

银河麒麟v10 二进制安装包 安装mysql 8.35

银河麒麟v10 二进制安装包 安装mysql 8.35 1、卸载mariadb2、下载Mysql安装包3、安装Mysql 8.353.1、安装依赖包3.2、安装Mysql3.3、安装后配置 1、卸载mariadb 由于银河麒麟v10系统默认安装了mariadb 会与Mysql相冲突&#xff0c;因此首先需要卸载系统自带的mariadb 查看系统…