草庐IT

MOPSO 多目标粒子群算法

Nicer0815 2023-04-18 原文

MOPSO 多目标粒子群算法

1、算法简介

多目标粒子群(MOPSO)算法是由CarlosA. Coello Coello等人在2004年提出,目的是将原来只能用在单目标上的粒子群算法(PSO)应用于多目标上。

1.1、相关知识点

支配(Dominance ) :在多目标优化问题中,如果个体p至少有一个目标比个体q好,而且个体p的所有目标都不比q差;那么称个体p支配个体q

序值(Rank):如果p支配q,那么p的序值比q低;如果p和q互不支配,那么p和q有相同的序值

拥挤距离(Crowding Distance):表示个体之间的拥挤程度,测量相同序值个体之间的距离。

帕累托(Pareto):https://blog.csdn.net/m0_59838738/article/details/121588306

粒子群算法(PSO)承接我的博客

2、算法描述

2.1、PSO 对比 MOPSO

PSO:

|

MOPSO:

MOPSO注:

  • 根据pareto支配原则,计算得到Archive集(存放当前的非劣解)计算局部最优pbest
  • 计算Archive集中的拥挤度在Archive集选择全局最优gbest
  • 更新粒子的速度和位置,并计算适应值更新Archive集(需注意防止溢出)

结论:可以看出PSO和MOPSO的大框架一致,MOPSO只是根据多目标问题改进了PSO中的pbest和gbest的选取方法

  • pbest的选取:
    • 单目标问题中,PSO可以根据适应度直接找出该粒子历史最好的位置;
    • 多目标问题中,MOPSO找出该粒子历史最好的位置(保存于该粒子结构体的一个属性中);
      • 如果在更新当前粒子的历史最好位置发现当前位置历史最佳互不支配,0.5概率随机选一个
  • gbest的选取
    • 单目标问题中,PSO可以根据适应度直接找出当前最好的粒子;
    • 多目标问题中,MOPSO根据Pareto找出当前最好的粒子集合,至于最后精确到哪个粒子,找到最不拥挤的那个粒子

2.2、密度的计算

我的NSGA-II的博客的2.3拥挤距离类似,这里采用了网格法:

把目标空间用网格等分成小区域,以每个区域中包含的粒子数作为粒子的密度信息。粒子所在网格中包含的粒子数越多,其密度值越大,反之越小。

以二维目标空间最小化优化问题为例,密度信息估计算法的具体实现过程如下:

(1)假设我们现在得到一代种群粒子如下:

(2)根据输入的粒子坐标,可以确定每个维度的最大最小值,计算成坐标保存:即图示的两个黑点坐标

(3)划分格子,一般情况下我们会对边界进行一次膨胀,然后根据nGrid参数进行每个维度的等额划分:假设我们设置了参数nGrid = 3即每个维度划分3个网格

(4)存储格子信息,如上下界,格子编号等。然后根据粒子坐标即可统计格子内的粒子数。

3、算法流程图

4、代码实操

下面展示ZDT1~4系列问题的求解代码

4.1、代码

(1)文件目录:

(2)网格创建函数

function Grid = CreateGrid(pop, nGrid, alpha)

    c = [pop.Cost];

    %M = min(A,[],dim) 返回维度 dim 上的最小元素。例如,如果 A 为矩阵,则 min(A,[],2) 是包含每一行的最小值的列向量。
    cmin = min(c, [], 2);
    cmax = max(c, [], 2);
    
    dc = cmax-cmin;

    %网格边界外扩
    cmin = cmin-alpha*dc;
    cmax = cmax+alpha*dc;
    
    nObj = size(c, 1);
    
    %网格上下界
    empty_grid.LB = [];
    empty_grid.UB = [];
    Grid = repmat(empty_grid, nObj, 1);
    
    for j = 1:nObj
        %y = linspace(x1,x2,n) 生成 n 个点。这些点的间距为 (x2-x1)/(n-1)。
        cj = linspace(cmin(j), cmax(j), nGrid+1);       % nGrid是设置好的参数
        
        Grid(j).LB = [-inf cj];
        Grid(j).UB = [cj +inf];
        
    end

end

(3)支配计算函数1

function pop = DetermineDomination(pop)

    nPop = numel(pop);
    
    for i = 1:nPop
        pop(i).IsDominated = false;
    end
    
    for i = 1:nPop-1
        for j = i+1:nPop
            % b = all(x <= y) && any(x<y);
            if Dominates(pop(i), pop(j))  %i支配j
               pop(j).IsDominated = true;
            end
            
            if Dominates(pop(j), pop(i))
               pop(i).IsDominated = true;
            end
            % 有重复比对的过程
        end
    end

end

(4)支配计算函数2

function b = Dominates(x, y)

    if isstruct(x)
        x = x.Cost;
    end
    
    if isstruct(y)
        y = y.Cost;
    end

    b = all(x <= y) && any(x<y);

end

(5)网格查找函数,遍历粒子,统计网格

function particle = FindGridIndex(particle, Grid)

    nObj = numel(particle.Cost);
    
    nGrid = numel(Grid(1).LB);
    
    particle.GridSubIndex = zeros(1, nObj);
    
    for j = 1:nObj
        
        particle.GridSubIndex(j) = ...
            find(particle.Cost(j)<Grid(j).UB, 1, 'first');
        
    end

    particle.GridIndex = particle.GridSubIndex(1);
    for j = 2:nObj
        particle.GridIndex = particle.GridIndex-1;
        particle.GridIndex = nGrid*particle.GridIndex;
        particle.GridIndex = particle.GridIndex+particle.GridSubIndex(j);
    end
    
end

(6)轮盘选择函数

function i = RouletteWheelSelection(P)

    r = rand;
    
    C = cumsum(P);
    
    i = find(r <= C, 1, 'first');

end

(7)gbest选择函数,选一个当全局最优

function leader = SelectLeader(rep, beta)

    % Grid Index of All Repository Members
    GI = [rep.GridIndex];
    
    % Occupied Cells
    OC = unique(GI);
    
    % Number of Particles in Occupied Cells
    N = zeros(size(OC));
    for k = 1:numel(OC)
        N(k) = numel(find(GI == OC(k)));
    end
    
    % Selection Probabilities
    P = exp(-beta*N);
    P = P/sum(P);
    
    % Selected Cell Index 轮盘选择
    sci = RouletteWheelSelection(P);
    
    % Selected Cell
    sc = OC(sci);
    
    % Selected Cell Members
    SCM = find(GI == sc);
    

    % 网格里可能还有多个粒子 再随机选一个
    % Selected Member Index
    smi = randi([1 numel(SCM)]);
    
    % Selected Member
    sm = SCM(smi);
    
    % Leader
    leader = rep(sm);

end

(8)绘图函数

function PlotCosts(pop, rep)

    pop_costs = [pop.Cost];
    plot(pop_costs(1, :), pop_costs(2, :), 'ko');
    hold on;
    
    rep_costs = [rep.Cost];
    plot(rep_costs(1, :), rep_costs(2, :), 'r*');
    
    xlabel('1^{st} Objective');
    ylabel('2^{nd} Objective');
    
    grid on;
    
    hold off;

end

(9)ZDT1~4

function z = ZDT1(x)

    n = numel(x);

    f1 = x(1);
    
    g = 1+9/(n-1)*sum(x(2:end));
    
    h = 1-sqrt(f1/g);
    
    f2 = g*h;
    
    z = [f1
       f2];

end

function z = ZDT2(x)

    n = numel(x);

    f1 = x(1);
    
    g = 1+9/(n-1)*sum(x(2:end));
    
    h = 1-(f1/g)^2;
    
    f2 = g*h;
    
    z = [f1
       f2];

end
function z = ZDT3(x)

    n = numel(x);

    f1 = x(1);
    
    g = 1+9/(n-1)*sum(x(2:end));
    
    %h = 1-(f1/g)^2;  % ZDT2与3的不同之处
    h = (1-(f1/g)^0.5-(f1/g)*sin(10*pi*f1));
    
    f2 = g*h;
    
    z = [f1
       f2];

end
function z = ZDT4(x)

    n = numel(x);

    f1 = x(1);

    sum=0;
    for i=2:n
        sum = sum+(x(i)^2-10*cos(4*pi*x(i)));
    end

    g = 1+9*10+sum;

    h = (1-(f1/g)^0.5);
    
    f2 = g*h;
    
    z = [f1
       f2];

end

(10)主函数

clc;
clear;
close all;

%% Problem Definition

CostFunction = @(x) ZDT3(x);      % Cost Function

nVar = 5;             % 5个决策变量

VarSize = [1 nVar];   % Size of Decision Variables Matrix

VarMin = 0;          % Lower Bound of Variables
VarMax = 1;          % Upper Bound of Variables


%% MOPSO Parameters

MaxIt = 200;           % 迭代次数

nPop = 200;            % 种群大小

nRep = 100;            % 精英库

w = 0.5;              % 惯性权重
wdamp = 0.99;         % 惯性权重的衰减因子(阻尼)
c1 = 1;               % 个体学习因子
c2 = 2;               % 全局学习因子

nGrid = 7;            % 每个维度的网格数
alpha = 0.1;          % 膨胀率  网格边界外扩大小的因子

beta = 2;             % Leader Selection Pressure
gamma = 2;            % Deletion Selection Pressure

mu = 0.1;             % 变异率

%% Initialization

empty_particle.Position = [];
empty_particle.Velocity = [];
empty_particle.Cost = [];
empty_particle.Best.Position = [];
empty_particle.Best.Cost = [];
empty_particle.IsDominated = [];
empty_particle.GridIndex = [];
empty_particle.GridSubIndex = [];

pop = repmat(empty_particle, nPop, 1);

for i = 1:nPop
    
    pop(i).Position = unifrnd(VarMin, VarMax, VarSize);
    
    pop(i).Velocity = zeros(VarSize);
    
    pop(i).Cost = CostFunction(pop(i).Position);  % CostFunction = @(x) ZDT(x); 适应度
    
    
    % Update Personal Best
    pop(i).Best.Position = pop(i).Position;
    pop(i).Best.Cost = pop(i).Cost;
    
end

% 计算种群的支配情况
pop = DetermineDomination(pop);

% 取出没有被支配的pop元素,存放到rep
rep = pop(~[pop.IsDominated]);

% 根据粒子分布画出网格
Grid = CreateGrid(rep, nGrid, alpha);

% 根据粒子位置确定所处网格
for i = 1:numel(rep)
    rep(i) = FindGridIndex(rep(i), Grid);
end


%% MOPSO Main Loop

for it = 1:MaxIt
    
    for i = 1:nPop
        
        gbest = SelectLeader(rep, beta);
        
        pop(i).Velocity = w*pop(i).Velocity ...
            +c1*rand(VarSize).*(pop(i).Best.Position-pop(i).Position) ...
            +c2*rand(VarSize).*(gbest.Position-pop(i).Position);
        
        pop(i).Position = pop(i).Position + pop(i).Velocity;
        
        pop(i).Position = max(pop(i).Position, VarMin);
        pop(i).Position = min(pop(i).Position, VarMax);
        
        pop(i).Cost = CostFunction(pop(i).Position);
        
        % 更新i粒子历史最优
        if Dominates(pop(i), pop(i).Best)
            pop(i).Best.Position = pop(i).Position;
            pop(i).Best.Cost = pop(i).Cost;
            
        elseif Dominates(pop(i).Best, pop(i))
            % Do Nothing
            
        else
            if rand<0.5
                pop(i).Best.Position = pop(i).Position;
                pop(i).Best.Cost = pop(i).Cost;
            end
        end
        
    end
    
    % Add Non-Dominated Particles to REPOSITORY
    % 把更新后的rank = 1的粒子再加到rep
    rep = [rep
         pop(~[pop.IsDominated])]; %#ok
    
    % Determine Domination of New Resository Members
    % 上一代的Non-Dominated粒子和当前代的粒子进行支配判断
    rep = DetermineDomination(rep);
    
    % Keep only Non-Dminated Memebrs in the Repository
    rep = rep(~[rep.IsDominated]);
    
    % Update Grid
    Grid = CreateGrid(rep, nGrid, alpha);

    % Update Grid Indices
    for i = 1:numel(rep)
        rep(i) = FindGridIndex(rep(i), Grid);
    end
    
    % Check if Repository is Full
    if numel(rep)>nRep
        
        Extra = numel(rep)-nRep;
        for e = 1:Extra
            % 轮盘删一个,类似选取pbest的流程
            rep = DeleteOneRepMemebr(rep, gamma);
        end
        
    end
    
    % Plot Costs
    figure(1);
    PlotCosts(pop, rep);
    pause(0.01);
    
    % Show Iteration Information
    disp(['Iteration ' num2str(it) ': Number of Rep Members = ' num2str(numel(rep))]);
    
    % Damping Inertia Weight
    w = w*wdamp;
    
end

之前漏掉的函数DeleteOneRepMemebr【sorry】

function rep = DeleteOneRepMemebr(rep, gamma)

    % Grid Index of All Repository Members
    GI = [rep.GridIndex];
    
    % Occupied Cells
    OC = unique(GI);
    
    % Number of Particles in Occupied Cells
    N = zeros(size(OC));
    for k = 1:numel(OC)
        N(k) = numel(find(GI == OC(k)));
    end
    
    % Selection Probabilities
    P = exp(gamma*N);
    P = P/sum(P);
    
    % Selected Cell Index
    sci = RouletteWheelSelection(P);
    
    % Selected Cell
    sc = OC(sci);
    
    % Selected Cell Members
    SCM = find(GI == sc);
    
    % Selected Member Index
    smi = randi([1 numel(SCM)]);
    
    % Selected Member
    sm = SCM(smi);
    
    % Delete Selected Member
    rep(sm) = [];

end

4.2、ZDT1~4的运行结果

|

|
|

有关MOPSO 多目标粒子群算法的更多相关文章

  1. 区块链之加解密算法&数字证书 - 2

    目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非

  2. 100个python算法超详细讲解:画直线 - 2

    1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva

  3. ruby - 在 Ruby 中实现 Luhn 算法 - 2

    我一直在尝试用Ruby实现Luhn算法。我一直在执行以下步骤:该公式根据其包含的校验位验证数字,该校验位通常附加到部分帐号以生成完整帐号。此帐号必须通过以下测试:从最右边的校验位开始向左移动,每第二个数字的值加倍。将乘积的数字(例如,10=1+0=1、14=1+4=5)与原始数字的未加倍数字相加。如果总模10等于0(如果总和以零结尾),则根据Luhn公式该数字有效;否则无效。http://en.wikipedia.org/wiki/Luhn_algorithm这是我想出的:defvalidCreditCard(cardNumber)sum=0nums=cardNumber.to_s.s

  4. Ruby 斐波那契算法 - 2

    下面是我写的一个计算斐波那契数列中的值的方法:deffib(n)ifn==0return0endifn==1return1endifn>=2returnfib(n-1)+(fib(n-2))endend它工作到n=14,但在那之后我收到一条消息说程序响应时间太长(我正在使用repl.it)。有人知道为什么会这样吗? 最佳答案 Naivefibonacci进行了大量的重复计算-在fib(14)fib(4)中计算了很多次。您可以将内存添加到您的算法中以使其更快:deffib(n,memo={})ifn==0||n==1returnnen

  5. ruby-on-rails - Rails add_index 算法 : :concurrently still causes database lock up during migration - 2

    为了防止在迁移到生产站点期间出现数据库事务错误,我们遵循了https://github.com/LendingHome/zero_downtime_migrations中列出的建议。(具体由https://robots.thoughtbot.com/how-to-create-postgres-indexes-concurrently-in概述),但在特别大的表上创建索引期间,即使是索引创建的“并发”方法也会锁定表并导致该表上的任何ActiveRecord创建或更新导致各自的事务失败有PG::InFailedSqlTransaction异常。下面是我们运行Rails4.2(使用Acti

  6. ruby - 趋势算法 - 2

    我正在开发一个类似微论坛的项目,其中一个特殊用户发布一条快速(接近推文大小)的主题消息,订阅者可以用他们自己的类似大小的消息来响应。直截了当,没有任何形式的“挖掘”或投票,只是每个主题消息的响应按时间顺序排列。但预计会有很高的流量。我们想根据它们引起的响应嗡嗡声来标记主题消息,使用0到10的等级。在谷歌上搜索了一段时间的趋势算法和开源社区应用示例,到目前为止已经收集到两个有趣的引用资料,但我还没有完全理解它们:Understandingalgorithmsformeasuringtrends,关于使用基线趋势算法比较维基百科页面浏览量的讨论,在SO上。TheBritneySpearsP

  7. ruby - Watir-Webdriver 是否支持点击目标为 javascript 的链接? - 2

    我是Ruby和Watir-Webdriver的新手。我有一套用VBScript编写的站点自动化程序,我想将其转换为Ruby/Watir,因为我现在必须支持Firefox。我发现我真的很喜欢Ruby,而且我正在研究Watir,但我已经花了一周时间试图让Webdriver显示我的登录屏幕。该站点以带有“我同意”区域的“警告屏幕”开头。用户点击我同意并显示登录屏幕。我需要单击该区域以显示登录屏幕(这是同一页面,实际上是一个表单,只是隐藏了)。我整天都在用VBScript这样做:objExplorer.Document.GetElementsByTagName("area")(0).click

  8. Ruby - 不支持的密码算法 (AES-256-GCM) - 2

    我收到错误:unsupportedcipheralgorithm(AES-256-GCM)(RuntimeError)但我似乎具备所有要求:ruby版本:$ruby--versionruby2.1.2p95OpenSSL会列出gcm:$opensslenc-help2>&1|grepgcm-aes-128-ecb-aes-128-gcm-aes-128-ofb-aes-192-ecb-aes-192-gcm-aes-192-ofb-aes-256-ecb-aes-256-gcm-aes-256-ofbRuby解释器:$irb2.1.2:001>require'openssl';puts

  9. java实现Dijkstra算法 - 2

    文章目录一.Dijkstra算法想解决的问题二.Dijkstra算法理论三.java代码实现一.Dijkstra算法想解决的问题解决的问题:求解单源最短路径,即各个节点到达源点的最短路径或权值考察其他所有节点到源点的最短路径和长度局限性:无法解决权值为负数的情况二.Dijkstra算法理论参数:S记录当前已经处理过的源点到最短节点U记录还未处理的节点dist[]记录各个节点到起始节点的最短权值path[]记录各个节点的上一级节点(用来联系该节点到起始节点的路径)Dijkstra算法步骤:(1)初始化:顶点集S:节点A到自已的最短路径长度为0。只包含源点,即S={A}顶点集U:包含除A外的其他顶

  10. 对于体育新闻中文文本关键字提取有哪些关键字提取算法及其步骤 - 2

    对于体育新闻中文文本的关键字提取,常用的算法包括TF-IDF、TextRank和LDA等。它们的基本步骤如下:1.TF-IDF算法: -将文本进行分词和词性标注处理。-统计每个词在文本中的词频(TF)。-计算每个词在整个语料库中出现的文档频率(DF)和逆文档频率(IDF)。-计算每个词的TF-IDF值,并按照值的大小进行排序,选择排名前几的词作为关键字。2.TextRank算法:-将文本进行分词和词性标注处理。-将分词结果转化成图模型,每个词语为节点,根据词语之间的共现关系建立边。-对图模型进行迭代计算,计算每个节点的PageRank值,表示该节点的重要性。-选择排名前几的节点作为关键字。3.

随机推荐