双层优化入门(3)—基于智能优化算法的求解方法(附matlab代码)

news2025/1/20 14:55:56

        前面两篇博客介绍了双层优化的基本原理和使用KKT条件求解双层优化的方法,以及使用yalmip工具箱求解双层优化的方法:

双层优化入门(1)—基本原理与求解方法

双层优化入门(2)—基于yalmip的双层优化求解(附matlab代码)

        除了数学规划方法之外,还可采用智能优化算法求解双层优化问题,一般在上层优化中采用智能优化算法,下层优化使用数学规划方法;也可以在上下层优化中都采用智能优化算法,这篇博客将进行详细介绍。

        算例依旧使用上面两篇博客中的线性双层优化问题,由于这个优化问题比较简单,我们采用最基础的粒子群算法进行求解。

​ 

1.粒子群算法

        1995年,受到鸟群觅食行为的规律性启发,James Kennedy和Russell Eberhar建立了一个简化算法模型,经过多年改进最终形成了粒子群优化算法(Particle Swarm Optimization, PSO) ,也可称为粒子群算法。

        关于算法的原理及步骤可以参考这篇博客:

粒子群优化算法(Particle Swarm Optimization, PSO)的详细解读 - 知乎 (zhihu.com)

        我们假设目标函数是平方和最小,也就是:

        假设种群数为200,问题维度为10,最大迭代次数为200,位置上下限分别为10,-10,速度上下限为5,-5,惯性权重取固定值0.9,自我学习因子以及群体学习因子都取1.5,Matlab代码如下:

%% 清除变量
clc
clear
close all
warning off
%% 设置种群参数
sizepop = 200;                      % 初始种群个数
dim = 10;                           % 空间维数
ger = 200;                          % 最大迭代次数    
x_max = 10*ones(1,dim);             % 位置上限
x_min = -10*ones(1,dim);            % 位置下限
v_max = 5*ones(1,dim);              % 速度上限
v_min = -5*ones(1,dim);             % 速度下限
w=0.9;                              % 惯性权重
c_1 = 1.5;                          % 自我学习因子
c_2 = 1.5;                          % 群体学习因子 
%% 种群初始化
pop=x_min+rand(sizepop,dim).*(x_max-x_min);     % 初始化种群
pop_v=v_min+rand(sizepop,dim).*(v_max-v_min);   % 初始化种群速度        
pop_zbest=pop(1,:);                             % 初始化群体最优位置
pop_gbest=pop;                                  % 初始化个体最优位置
fitness=zeros(1,sizepop);                       % 所有个体的适应度
fitness_zbest=inf;                              % 初始化群体最优适应度
fitness_gbest=inf*ones(1,sizepop);              % 初始化个体最优适应度
% 初始的适应度
for k=1:sizepop
    % 计算适应度值
    fitness(k)=sum(pop(k,:).^2);
    if fitness(k)<fitness_zbest
        fitness_zbest=fitness(k);
        pop_zbest=pop(k,:);
    end
end
history_pso=zeros(1,ger);            % 粒子群历史最优适应度值
%% 迭代求最优解
iter=1;
while iter <= ger
    for k=1:sizepop
        % 更新速度并对速度进行边界处理 
        pop_v(k,:)= w * pop_v(k,:) + c_1*rand*(pop_gbest(k,:)-pop(k,:))+c_2*rand*(pop_zbest-pop(k,:));
        for kk=1:dim
            if  pop_v(k,kk) > v_max(kk)
                pop_v(k,kk) = v_max(kk);
            end
            if  pop_v(k,kk) < v_min(kk)
                pop_v(k,kk) = v_min(kk);
            end
        end
        % 更新位置并对位置进行边界处理
        pop(k,:)=pop(k,:)+pop_v(k,:);
        for kk=1:dim
            if  pop(k,kk) > x_max(kk)
                pop(k,kk) = x_max(kk);
            end
            if  pop(k,kk) < x_min(kk)
                pop(k,kk) = x_min(kk);
            end
        end
        % 更新适应度值
        fitness(k)=sum(pop(k,:).^2);
        if fitness(k)<fitness_zbest
            fitness_zbest=fitness(k);
            pop_zbest=pop(k,:);
        end
        if fitness(k)<fitness_gbest(k)
            fitness_gbest(k)=fitness(k);
            pop_gbest(k,:)=pop(k,:);
        end
    end
    history_pso(iter)=fitness_zbest;
    disp(['PSO第',num2str(iter),'次迭代最优适应度=',num2str(fitness_zbest)])
    iter=iter+1;
end
disp(['最优解:x=',num2str(pop_zbest)])
disp(['最优函数值=',num2str(fitness_zbest)])
plot(history_pso,'linewidth',1)
ylabel('最优适应度值')
xlabel('迭代次数')

        运行结果如下:

        我们知道最优解是当所有变量都取0时,最优函数值为0,上面显示采用粒子群算法求出的显然并不是全局最优解,只是一个局部最优解。这也是智能优化算法无法避免的问题,即使是一个非常简单的目标函数,求出的结果也无法保证是全局最优,那么当目标函数变复杂时,情况将会更糟糕。现在对智能优化算法的研究非常多,各种动植物园算法、各种改进都层出不穷,但还是无法从根本上解决算法无法保证全局收敛的问题。

        所以,只有在数学模型比较复杂,非线性条件很多,而且对结果的误差是可以接受的情况下,才建议使用智能优化算法进行求解。

        下面以粒子群算法为例,介绍采用智能优化算法求解双层优化问题的方法。 

2.智能优化算法中对约束条件的处理

        上面提供的代码中,含有的约束条件是x∈[-10,10],直接可以通过粒子位置的上下限进行约束,但其他形式的约束就没办法这样处理了,常用的处理方式有三类,以上面提到的双层优化问题的上层优化为例,分别介绍这几种方法:

1)通过加罚函数的方式将有约束的问题转为无约束问题:

        首先定义罚函数: 

         然后将罚函数加入原来的目标函数中形成新的目标函数:

其中,p是惩罚因子。这样处理,可以使得违反约束的粒子目标函数值变得很大,从而促使粒子朝着遵守约束的区域聚集。这种方式在过去非常常用,但我自己不太喜欢这种方式,原因待会我会解释。假设惩罚因子为1,新的目标函数可以用matlab代码表示出来: 

function fitness=fitness_fun_method1(pop)
    x=pop(1);
    y=pop(2);
    punish=0;
    p=1;
    if -2*x+3*y > 12
        punish=punish+p*(-2*x+3*y-12);
    end
    if x+y > 14
        punish=punish+p*(x+y-14);
    end
    fitness=-x-2*y+punish;
end

        运行结果如下:

        很奇怪的是,明明最优解是x=6,y=8,最优函数值是-22,但求出的结果却完全不一样,甚至是违反约束条件的。

        这就是罚函数的缺点,因为你把约束条件当作罚函数加进目标函数里,当惩罚因子选的不合适时,实际上是改变了目标,很有可能导致最优解和最优函数值都发生了变化,和你原来的目标背道而驰了。解决的办法就是要选择一个合适的惩罚因此,比如我改成9,再重新求解:

        这时候得到的结果就是正常的了。

        但说实话,我在运行之前也不知道我滴惩罚因子到底多大合适,如果要求解的问题比较复杂,运行时间很长,可能一个错误的惩罚因子就能让你白忙活半天。所以我不太喜欢这种方式。

2)当约束被违反时,给这个粒子赋一个很差的适应度值;

        第二种方式说起来就很简单,就是让违反约束的粒子适应度很差。如果是最小化问题就给他赋一个很大的值,如果是最大化问题就赋一个很小的值。这时候目标函数Matlab代码可以这样写:

function fitness=fitness_fun_method2(pop)
    x=pop(1);
    y=pop(2);
    if -2*x+3*y > 12
        fitness=999;
    end
    if x+y > 14
        fitness=999;
    end
    if -2*x+3*y <= 12 && x+y <= 14
        fitness=-x-2*y;
    end
end

运行时可以求出最优解:

3)初始化粒子时,仅产生满足约束条件的粒子,当约束被违反时,重新生成一个满足约束的粒子。

        这种方式和其他两种方式的角度不同,是从粒子的初始化和更新的角度进行考虑,而不是从适应度函数的角度出发。

        首先,在初始化种群时,保证生成的粒子都是满足约束条件的,可以采用下面的代码:

while true
    pop0=x_min+rand(sizepop*10,dim).*(x_max-x_min);
    x = pop0(:,1);
    y = pop0(:,2);
    % 使用逐元素运算检查约束条件
    mask = (-2*x+3*y<=12) & (x+y<=14) ;
    % 如果点的数量已经足够了,则退出循环
    if nnz(mask) >= sizepop
        pop=[x(mask), y(mask)];
        break;
    end
end
pop=pop(1:sizepop,:);                           % 初始化种群

        目标函数可以不考虑任何约束条件:

function fitness=fitness_fun_method3(pop)
    x=pop(1);
    y=pop(2);
    fitness=-x-2*y;
end

        但是当更新粒子之后如果不满足约束条件,需要将该粒子修复为满足约束的粒子:

% 更新位置并对位置进行边界处理
pop(k,:)=pop(k,:)+pop_v(k,:);
x=pop(k,1);
y=pop(k,2);
% 修复不满足约束的粒子
if (-2*x+3*y > 12 )|| (x+y > 14)
    while true
        pop0=x_min+rand(10,dim).*(x_max-x_min);
        x = pop0(:,1);
        y = pop0(:,2);
        % 使用逐元素运算检查约束条件
        mask = (-2*x+3*y<=12) & (x+y<=14) ;
        % 如果数量已经足够了,则退出循环
        if nnz(mask) >= 1
            pop_test=[x(mask), y(mask)];
            pop(k,:)=pop_test(1,:);
            break;
        end
    end
end

        优化结果如下:

        我们可以看到,在初始化种群以及更新粒子时都考虑约束条件时,也可以求出较优的解。

        此外根据所求优化问题的实际情况不同,也可以将上面几种对约束条件的不同处理方式相结合。例如,在初始化以及更新种群时考虑一部分约束,另一部分约束采用罚函数的方式添加到目标函数中,此处不再赘述。

3.上层优化采用粒子群算法,下层优化使用yalmip或粒子群算法进行求解

        对于双层优化的问题求解,第一种方式是上层优化采用智能优化算法,下层问题使用yalmip等工具箱直接求出最优解。第二种方式是上下层优化都采用智能优化算法。还是以上面那个线性双层优化问题为例,采用第二种方法处理约束条件,说明一下采用智能优化算法求解双层优化问题的具体步骤:

1)设置算法参数

        采用智能优化算法求解上层优化问题时,由于上下层需同时优化,并进行迭代,为避免求解时间过长,种群规模和迭代次数不宜过大,在这里设置为30和50。另外,变量y的取值需要在下层优化中进行决策,上层优化只需要决策变量x,因此上层优化的粒子群算法问题维度设置为1。

%% 设置种群参数
sizepop = 30;                       % 初始种群个数
dim = 1;                            % 空间维数
ger = 50;                           % 最大迭代次数    
x_max = 14*ones(1,dim);             % 位置上限
x_min = zeros(1,dim);               % 位置下限
v_max = 7*ones(1,dim);              % 速度上限
v_min = -7*ones(1,dim);             % 速度下限
w=0.9;                              % 惯性权重
c_1 = 1.5;                          % 自我学习因子
c_2 = 1.5;                          % 群体学习因子

2)初始化种群

%% 种群初始化
pop=x_min+rand(sizepop,dim).*(x_max-x_min);     % 初始化种群
pop_v=v_min+rand(sizepop,dim).*(v_max-v_min);   % 初始化种群速度        
pop_zbest=pop(1,:);                             % 初始化群体最优位置
pop_gbest=pop;                                  % 初始化个体最优位置
fitness=zeros(1,sizepop);                       % 所有个体的适应度
fitness_zbest=inf;                              % 初始化群体最优适应度
fitness_gbest=inf*ones(1,sizepop);              % 初始化个体最优适应度

3)计算种群初始适应度

for k=1:sizepop
    % 计算适应度值
    fitness(k)=up_fitness_fun(pop(k,:));
    if fitness(k)<fitness_zbest
        fitness_zbest=fitness(k);
        pop_zbest=pop(k,:);
    end
end
history_pso=zeros(1,ger);            % 粒子群历史最优适应度值

        粒子的适应度函数(也就是优化问题的目标函数取值)取决于变量x和y的值,而y的取值又由下层优化决定,因此求适应度函数的过程其实就是一个迭代过程,上层优化向下层优化传递变量x,下层优化根据x的取值和自身的目标函数以及约束条件,得到y的取值,然后向上层优化传递,最终根据x和y的取值综合得到目标函数,我们这里选择yalmip求解下层优化问题,代码如下:

%% up_fitness_fun.m
function fitness=up_fitness_fun(pop)
    x=pop;
    y=main_down(x);
    punish=0;
    if -2*x+3*y > 12
        punish=punish+999;
    end
    if x+y > 14
        punish=punish+999;
    end
    fitness=-x-2*y+punish;
end
%% main_down.m
function best_y=main_down(x)
    y=sdpvar(1);
    Constraints=[-3*x+y <= -3 , 3*x+y <= 30 ];
    objective=-y;
    ops=sdpsettings('verbose', 0 , 'solver', 'cplex');
    optimize(Constraints,objective,ops);
    best_y=value(y);
end

4)迭代求最优解

        最终优化结果如下:

  

        求解结果和前两篇博客都一样(非常接近全局最优解x=8,y=6),但是因为每次迭代时,每个上层粒子都需要将自身的参数传递给下层粒子求解下层优化问题,意味着完成计算过程需要sizepop×ger=1500次下层优化,所以需要的时间很长。如果问题规模更大,模型更复杂,采用智能优化算法求解双层优化问题所需的时间将会更多,这时候就可以考虑将非线性双层优化问题模型简化为线性双层优化,然后再使用KKT条件转为单层优化问题进行求解。这样求解时间会大大缩短,可能也会提高计算精度(智能优化算法的局部收敛问题)

完整代码可以从这个链接获取:

基于智能优化算法的双层优化求解(matlab代码)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot+vue大学生体质测试管理系统(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的大学生体质测试管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xf…

how2heap-fastbin_dup.c

不同libc版本的fastbin_dup.c源码有点小区别&#xff1a;主要是有tcache的&#xff0c;需要先填充 以下为有tcache的源码示例&#xff1a; #include <stdio.h> #include <stdlib.h> #include <assert.h>int main() {setbuf(stdout, NULL);printf("This…

诗词·宇宙之梦

宇宙之梦 重力枷锁必将断&#xff0c;携君翱翔万里空。 迷途夜路寻踪迹&#xff0c;一声呼唤莫轻忽。 寻觅中&#xff0c;见红瞳&#xff0c;决不装假觉清白。 黑泽之中君沉沦&#xff0c;放之不下心怎静。 重力终将解开放&#xff0c;卫星翔空自由翱。 重量减半去忧愁&#xf…

RobotFramework+Eclispe环境安装篇

环境安装是学习任何一个新东西的第一步&#xff0c;这一步没走舒坦&#xff0c;那后面就没有心情走下去了。 引用名句&#xff1a;工欲善其事必先利其器&#xff01;&#xff01; Robotframework&#xff1a;一款 自动化测试框架。 Eclipse&#xff1a;一款编辑工具。可以编…

Android MVVN 使用入门

MVVM&#xff08;Model-View-ViewModel&#xff09;是一种基于数据绑定的设计模式&#xff0c;它与传统的 MVC 和 MVP 模式相比&#xff0c;更加适合处理复杂的 UI 逻辑和数据展示。在 Android 开发中&#xff0c;MVVM 通常使用 Data Binding 和 ViewModel 实现。 下面是一个简…

正则化解决过拟合

本片举三个例子进行对比&#xff0c;分别是&#xff1a;不使用正则化、使用L2正则化、使用dropout正则化。 首先是前后向传播、加载数据、画图所需要的相关函数的reg_utils.py&#xff1a; # -*- coding: utf-8 -*-import numpy as np import matplotlib.pyplot as plt impor…

双层优化入门(2)—基于yalmip的双层优化求解(附matlab代码)

上一篇博客介绍了双层优化的基本原理和使用KKT条件求解双层优化的方法&#xff1a; 双层优化入门(1)—基本原理与求解方法 这篇博客将介绍使用yalmip的双层优化问题的求解方法。 1.KKT函数 通过调用yalmip工具箱中的KKT函数&#xff0c;可以直接求出优化问题的KKT条件&#x…

算法(一)—— 回溯(2)

文章目录 1 131 分割回文串2 93 复原 IP 地址 s.substr(n, m) // 从字符串s的索引n开始&#xff0c;向后截取m个字符 例&#xff1a; string s "aaabbbcccddd"; string s1 s.substr(2,3); 此时s1为abb 1 131 分割回文串 切割问题&#xff0c;前文均为组合问题。组…

【Promptulate】一个强大的LLM Prompt Layer框架

本文节选自笔者博客&#xff1a; https://www.blog.zeeland.cn/archives/promptulate666 项目地址&#xff1a;https://github.com/Undertone0809/promptulate &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是Zeeland&#xff0c;全栈领域优质创作者。&#x1f4dd;…

pyinstaller打包为.exe过程中的问题与解决方法

目录 问题一&#xff1a;.exe文件过大问题二&#xff1a;pyinstaller与opencv-python版本不兼容问题三&#xff1a;打开文件时提示***.pyd文件已存在问题四&#xff1a;pyinstaller打包时提示UPX is not available.另&#xff1a;查看CUDA成功配置的方法 pyinsatller -F -w mai…

瑞吉外卖 - 开发环境搭建(2)

某马瑞吉外卖单体架构项目完整开发文档&#xff0c;基于 Spring Boot 2.7.11 JDK 11。预计 5 月 20 日前更新完成&#xff0c;有需要的胖友记得一键三连&#xff0c;关注主页 “瑞吉外卖” 专栏获取最新文章。 相关资料&#xff1a;https://pan.baidu.com/s/1rO1Vytcp67mcw-PD…

网络编程启蒙

文章目录 局域网、广域网WAN口LAN口那么什么是局域网和广域网呢&#xff1f; IP地址IPV4动态规划ipNAT IPV6IPV6的普及IPV6的应用 端口号协议协议分层协议分层的好处 OSI物理层数据链路层网络层&#xff08;全局&#xff09;传输层负责应用层网络设备所在分层网络分层中的一组重…

mybatis-plus实现乐观锁和悲观锁

目录 定义 场景 乐观锁与悲观锁 模拟修改冲突数据库中增加商品表 乐观锁实现 悲观锁 定义 1&#xff09;乐观锁 首先来看乐观锁&#xff0c;顾名思义&#xff0c;乐观锁就是持比较乐观态度的锁。就是在操作数据时非常乐观&#xff0c;认为别的线程不会同时修改数据&#x…

红旅在线语料库网站 开发笔记

桂林红色旅游资源在线语料库网站 &#xff08;Guilin Red Culture Corpus&#xff09;提供双语文本检索和分享功能。供英语、翻译相关专业的爱好者&#xff0c;学生和老师学习使用。 该网站是对BiCorpus开源项目的二次开发(已获得原作者授权)。 项目仓库&#xff1a;RedCorpu…

小米miui14更新公测

一人内测&#xff0c;全员公测&#xff0c;懂得都懂[滑稽] 必应搜索醉里博客http://202271.xyz?miui 1月份有一部分机型就要公测了&#xff0c;相关用户愿意等的可以再等等。 本篇介绍最简单粗暴的替换法&#xff0c;不管你刷没刷过机都可以用这个方法偷渡MIUI14 ★★★评论…

区间预测 | MATLAB实现QRCNN-GRU卷积门控循环单元分位数回归时间序列区间预测

区间预测 | MATLAB实现QRCNN-GRU卷积门控循环单元分位数回归时间序列区间预测 目录 区间预测 | MATLAB实现QRCNN-GRU卷积门控循环单元分位数回归时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 1.Matlab实现基于QRCNN-GRU分位数回归卷积门控循环…

可靠性设计:元器件、零部件、原材料的选择与控制

通常&#xff0c;一个产品由各种基础产品(包括各种元器件、零部件等)构成。由于元器件、零部件的数量、品种众多&#xff0c;所以他们的性能、可靠性、费用等参数对整个系统性能、可靠性、寿命周期费用等的影响极大。 原材料则是各种基础产品的基本功能赖以实现的基础&#xf…

储氢合金/金属氢化物床层有效导热系数的数学模型

最近看到一篇有关“储氢合金/金属氢化物床层有效导热系数的数学模型”的论文&#xff0c;文章DOI&#xff1a;10.1016/j.energy.2023.127085&#xff0c;文章提到的数学物理模型还算好理解一些&#xff0c;特意分享给各位感兴趣的大佬。 一、物理模型简图和假设 文章里&#xf…

数模之Apriori关联算法

一、问题 中医证型的关联规则挖掘 背景&#xff1a; 中医药治疗乳腺癌有着广泛的适应证和独特的优势。从整体出发&#xff0c;调整机体气血、阴阳、脏腑功能的平衡&#xff0c;根据不同的临床证候进行辨证论治。确定“先证而治”的方向&#xff1a;即后续证侯尚未出现之前&am…

前后端分离博客】学习笔记04 --- 文件上传-策略模式

一、思路 我们定义一个接口&#xff08;就比如接下来要实现的文件上传接口&#xff09;我们定义所需要实现的策略实现类 A、B、C、D&#xff08;也就是项目中所使用的四种策略阿里云Oss上传、腾讯云Cos上传、七牛云Kodo上传、本地上传&#xff09;我们通过策略上下文来调用策略…