MOEA-D(基于分解的多目标进化算法)

MOEA-D(基于分解的多目标进化算法)

这里分享的只是我卸载GitHub上README.md文件(大纲),具体的使用请看GitHub中的XXXX-USE.md文件!

Github 地址

MOEA-D(基于分解的多目标进化算法)是一种用于多目标优化的进化算法,其核心思想是将多目标优化问题分解为多个单目标优化问题。下面是MOEA-D算法的几个主要特点和步骤:

主要特点

  1. 分解策略

    • 将多目标优化问题通过权重向量(lambda)划分为多个子问题。每个子问题对应一个权重向量,代表目标空间中的一个方向。
  2. 邻域交互

    • 每个子问题与其邻域内的其他子问题相互影响,这有助于保持种群的多样性并促进优良解的传播。
  3. 适应度评估

    • 通过计算每个个体与理想点的距离,评估其适应度。采用加权绝对差的最大值作为个体的代价。
  4. 多样性维护

    • 通过选择、交叉和变异等操作,保持种群的多样性,避免早熟收敛。

算法步骤

  1. 初始化

    • 随机生成初始种群和对应的权重向量,确定邻域关系。
  2. 循环迭代

    • 在每次迭代中,通过交叉和变异等操作生成新个体。
    • 更新每个个体的代价,使用分解代价函数评估解的质量。
    • 通过支配关系确定哪些个体被优先保留。
  3. 更新Pareto前沿

    • 在每次迭代后,更新估计的Pareto前沿,并在必要时进行个体的选择和替换。
  4. 终止条件

    • 当达到预设的最大迭代次数或满足其他停止条件时,算法结束,返回Pareto前沿的解集。

应用场景

MOEA-D算法广泛应用于工程优化、资源分配、路径规划等领域,尤其是在多个相互冲突的目标之间寻求平衡时表现出色。

CreateSubProblems.m 文件代码:

% 创建子问题的函数
% 输入参数:
% nObj - 目标函数的数量
% nPop - 种群数量
% T - 每个子问题的邻居数量

function sp = CreateSubProblems(nObj, nPop, T)

    % 初始化空的子问题结构体
    empty_sp.lambda = [];       % 存储子问题的权重向量
    empty_sp.Neighbors = [];    % 存储邻居子问题的索引

    % 使用空结构体复制生成种群数量的子问题
    sp = repmat(empty_sp, nPop, 1);
    
    % theta = linspace(0, pi/2, nPop); % 可选:均匀分布的角度,未使用

    for i = 1:nPop
        % 随机生成权重向量并进行归一化
        lambda = rand(nObj, 1);   
        lambda = lambda / norm(lambda);  % 归一化处理
        sp(i).lambda = lambda;  % 将权重向量存储到子问题中
        
        % 可选:使用角度生成权重向量,未使用
        % sp(i).lambda = [cos(theta(i))
        %                  sin(theta(i))];
    end

    % 从子问题中提取权重向量并计算距离矩阵
    LAMBDA = [sp.lambda]';  
    D = pdist2(LAMBDA, LAMBDA);  % 计算权重向量之间的欧氏距离
    
    for i = 1:nPop
        % 对距离进行排序,获取最近的T个邻居
        [~, SO] = sort(D(i, :));
        sp(i).Neighbors = SO(1:T);  % 存储邻居索引
    end

end

Crossover.m 文件代码:

% 交叉操作函数
% 输入参数:
% x1 - 第一个父代个体
% x2 - 第二个父代个体
% params - 参数结构体,包含交叉参数和变量范围

function y = Crossover(x1, x2, params)

    % 从参数中提取交叉相关参数
    gamma = params.gamma;       % 交叉幅度参数
    VarMin = params.VarMin;     % 变量的最小值
    VarMax = params.VarMax;     % 变量的最大值
    
    % 生成交叉因子,范围在[-gamma, 1 + gamma]之间
    alpha = unifrnd(-gamma, 1 + gamma, size(x1));
    
    % 进行线性组合生成子代个体
    y = alpha .* x1 + (1 - alpha) .* x2;

    % 确保生成的个体在变量范围内
    y = min(max(y, VarMin), VarMax);
    
end

DecomposedCost.m 文件代码:

% 计算分解代价的函数
% 输入参数:
% individual - 当前个体,可以是代价向量或结构体
% z - 理想点(目标函数的真实值)
% lambda - 权重向量,用于分解计算

function g = DecomposedCost(individual, z, lambda)

    % 检查个体是否包含代价值
    if isfield(individual, 'Cost')
        fx = individual.Cost;  % 从结构体中提取代价值
    else
        fx = individual;  % 如果不是结构体,直接使用个体作为代价
    end
    
    % 计算分解代价,使用加权绝对差的最大值
    g = max(lambda .* abs(fx - z));  % 计算当前个体与理想点的代价

end

DetermineDomination.m 文件代码:

% 确定种群中个体的支配关系的函数
% 输入参数:
% pop - 种群数组,包含多个个体

function pop = DetermineDomination(pop)

    nPop = numel(pop);  % 获取种群中个体的数量

    % 初始化每个个体的支配状态
    for i = 1:nPop
        pop(i).IsDominated = false;  % 默认未被支配
    end
    
    % 进行双重循环比较每对个体
    for i = 1:nPop
        for j = i + 1:nPop
            if Dominates(pop(i), pop(j))
                % 如果个体i支配个体j
                pop(j).IsDominated = true;  % 将j标记为被支配
                
            elseif Dominates(pop(j), pop(i))
                % 如果个体j支配个体i
                pop(i).IsDominated = true;  % 将i标记为被支配
                
            end
        end
    end

end

Dominates.m 文件代码:

% 判断个体x是否支配个体y的函数
% 输入参数:
% x - 被比较的个体
% y - 另一个被比较的个体

function b = Dominates(x, y)

    % 如果个体x是结构体,则提取代价值
    if isfield(x, 'Cost')
        x = x.Cost;  % 获取个体x的代价
    end

    % 如果个体y是结构体,则提取代价值
    if isfield(y, 'Cost')
        y = y.Cost;  % 获取个体y的代价
    end
    
    % 判断x是否支配y
    % x支配y当且仅当x在所有目标上都不大于y,并且至少在一个目标上严格小于y
    b = all(x <= y) && any(x < y);  

end

main.m 文件代码:

% 主程序文件
% 调用MOEA-D算法的主函数

moead;  % 执行MOEA-D算法的实现

moead.m 文件代码:

% MOEA-D算法的实现
clc;                % 清除命令行
clear;              % 清除工作区
close all;         % 关闭所有图形窗口

%% 问题定义

CostFunction = @(x) MOP2(x);  % 目标函数,使用MOP2函数进行评估

nVar = 3;             % 决策变量的数量

VarSize = [nVar 1];   % 决策变量矩阵的大小

VarMin = 0;           % 决策变量的下界
VarMax = 1;           % 决策变量的上界

nObj = numel(CostFunction(unifrnd(VarMin, VarMax, VarSize)));  % 目标函数的数量


%% MOEA/D设置

MaxIt = 100;  % 最大迭代次数

nPop = 50;    % 种群规模(子问题数量)

nArchive = 50;  % 存档数量

T = max(ceil(0.15 * nPop), 2);    % 邻居数量
T = min(max(T, 2), 15);            % 确保邻居数量在合理范围内

crossover_params.gamma = 0.5;  % 交叉参数
crossover_params.VarMin = VarMin;  % 决策变量下界
crossover_params.VarMax = VarMax;  % 决策变量上界

%% 初始化

% 创建子问题
sp = CreateSubProblems(nObj, nPop, T);

% 空个体(作为模板)
empty_individual.Position = [];  % 个体位置
empty_individual.Cost = [];      % 代价
empty_individual.g = [];          % 分解代价
empty_individual.IsDominated = [];  % 支配状态

% 初始化目标点
% z = inf(nObj, 1);  % 可选,未使用
z = zeros(nObj, 1);  % 初始化目标点为零

% 创建初始种群(随机初始化)
pop = repmat(empty_individual, nPop, 1);  % 复制空个体
for i = 1:nPop
    pop(i).Position = unifrnd(VarMin, VarMax, VarSize);  % 随机分布
    pop(i).Cost = CostFunction(pop(i).Position);  % 计算代价
    z = min(z, pop(i).Cost);  % 更新理想点
end

% 计算每个个体的分解代价
for i = 1:nPop
    pop(i).g = DecomposedCost(pop(i), z, sp(i).lambda);
end

% 确定种群的支配状态
pop = DetermineDomination(pop);

% 初始化估计的Pareto前沿
EP = pop(~[pop.IsDominated]);

%% 主循环

for it = 1:MaxIt
    for i = 1:nPop
        
        % 选择个体进行重组(交叉操作)
        K = randsample(T, 2);  % 随机选择两个邻居
        
        j1 = sp(i).Neighbors(K(1));  % 第一个邻居的索引
        p1 = pop(j1);  % 第一个邻居的个体
        
        j2 = sp(i).Neighbors(K(2));  % 第二个邻居的索引
        p2 = pop(j2);  % 第二个邻居的个体
        
        y = empty_individual;  % 创建一个新的空个体
        y.Position = Crossover(p1.Position, p2.Position, crossover_params);  % 交叉生成新个体
        
        y.Cost = CostFunction(y.Position);  % 计算新个体的代价
        
        z = min(z, y.Cost);  % 更新理想点
        
        % 更新邻居个体
        for j = sp(i).Neighbors
            y.g = DecomposedCost(y, z, sp(j).lambda);  % 计算新个体的分解代价
            if y.g <= pop(j).g
                pop(j) = y;  % 更新邻居个体
            end
        end
        
    end
    
    % 确定种群的支配状态
    pop = DetermineDomination(pop);
    
    ndpop = pop(~[pop.IsDominated]);  % 非支配个体
    
    EP = [EP; ndpop];  % 更新Pareto前沿
    
    EP = DetermineDomination(EP);  % 确定Pareto前沿的支配状态
    EP = EP(~[EP.IsDominated]);  % 仅保留非支配个体
    
    % 如果估计的Pareto前沿超过存档限制,则随机删除部分个体
    if numel(EP) > nArchive
        Extra = numel(EP) - nArchive;  % 计算需要删除的个体数量
        ToBeDeleted = randsample(numel(EP), Extra);  % 随机选择要删除的个体
        EP(ToBeDeleted) = [];  % 删除个体
    end
    
    % 绘制Pareto前沿
    figure(1);
    PlotCosts(EP);  % 绘制当前Pareto前沿
    pause(0.01);  % 暂停以便可视化更新

    % 显示当前迭代的信息
    disp(['Iteration ' num2str(it) ': Number of Pareto Solutions = ' num2str(numel(EP))]);
    
end

%% 结果输出

disp(' ');

EPC = [EP.Cost];  % 提取代价信息
for j = 1:nObj
    
    disp(['Objective #' num2str(j) ':']);
    disp(['      Min = ' num2str(min(EPC(j, :)))]);  % 输出最小值
    disp(['      Max = ' num2str(max(EPC(j, :)))]);  % 输出最大值
    disp(['    Range = ' num2str(max(EPC(j, :)) - min(EPC(j, :)))]);  % 输出范围
    disp(['    St.D. = ' num2str(std(EPC(j, :)))]);  % 输出标准差
    disp(['     Mean = ' num2str(mean(EPC(j, :)))]);  % 输出均值
    disp(' ');
    
end

MOP2.m 文件代码:

% MOP2多目标优化函数
% 输入参数:
% x - 决策变量的向量

function z = MOP2(x)

    n = numel(x);  % 获取决策变量的数量
    
    % 计算两个目标函数值
    z = [
        1 - exp(-sum((x - 1/sqrt(n)).^2));  % 第一个目标函数
        1 - exp(-sum((x + 1/sqrt(n)).^2))   % 第二个目标函数
    ];
    
end

PlotCosts.m 文件代码:

% 绘制目标函数代价的函数
% 输入参数:
% EP - 包含非支配个体的数组

function PlotCosts(EP)

    EPC = [EP.Cost];  % 提取所有非支配个体的代价值
    plot(EPC(1, :), EPC(2, :), 'x');  % 绘制目标函数的散点图
    xlabel('1^{st} Objective');  % 设置x轴标签
    ylabel('2^{nd} Objective');  % 设置y轴标签
    grid on;  % 显示网格
    
end

ZDT.m 文件代码:

% ZDT多目标优化函数
% 输入参数:
% x - 决策变量的向量

function z = ZDT(x)

    n = numel(x);  % 获取决策变量的数量
    f1 = x(1);  % 第一个目标函数值为决策变量的第一个元素
    g = 1 + 9 / (n - 1) * sum(x(2:end));  % 计算g函数,涉及其他决策变量
    h = 1 - sqrt(f1 / g);  % 计算h函数
    f2 = g * h;  % 计算第二个目标函数值
    
    z = [f1;   % 返回目标函数值
         f2];
end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值