遗传算法和粒子群算法求解非线性函数最大值问题

遗传算法(GA)和粒子群优化算法(PSO)实现,用于求解非线性函数最大值问题,并详细比较两种算法性能。

1. 问题定义与测试函数

%% 主程序:GA和PSO求解非线性函数最大值问题
clear; close all; clc;
warning('off', 'all');

%% 1. 定义测试函数
fprintf('=== GA和PSO求解非线性函数最大值 ===\n');

% 选择测试函数
test_function = 5;  % 1-6

% 获取函数信息
[func, func_name, bounds, dim, global_max, global_max_pos] = ...
    get_test_function(test_function);

% 显示函数信息
fprintf('测试函数: %s\n', func_name);
fprintf('维度: %d\n', dim);
fprintf('搜索范围: ');
for i = 1:dim
    fprintf('[%.2f, %.2f] ', bounds(i,1), bounds(i,2));
end
fprintf('\n');
fprintf('理论最大值: %.6f\n', global_max);
fprintf('理论最大值位置: [');
fprintf('%.2f ', global_max_pos);
fprintf(']\n\n');

%% 2. 算法参数设置
% 2.1 通用参数
params = struct();
params.maxIter = 100;           % 最大迭代次数
params.popSize = 50;           % 种群大小
params.dim = dim;              % 问题维度
params.bounds = bounds;        % 搜索边界
params.verbose = true;         % 显示详细信息
params.parallel = false;       % 是否使用并行计算

% 2.2 遗传算法参数
paramsGA = params;
paramsGA.crossoverProb = 0.8;  % 交叉概率
paramsGA.mutationProb = 0.1;   % 变异概率
paramsGA.selectionMethod = 'tournament';  % 选择方法: 'roulette', 'tournament'
paramsGA.crossoverMethod = 'blend';       % 交叉方法: 'single', 'two', 'blend'
paramsGA.mutationMethod = 'gaussian';     % 变异方法: 'uniform', 'gaussian'
paramsGA.elitismCount = 2;                % 精英保留数量

% 2.3 粒子群算法参数
paramsPSO = params;
paramsPSO.wMax = 0.9;          % 最大惯性权重
paramsPSO.wMin = 0.4;          % 最小惯性权重
paramsPSO.c1 = 2.0;            % 个体学习因子
paramsPSO.c2 = 2.0;            % 社会学习因子
paramsPSO.vMax = 0.2;          % 最大速度限制(相对于搜索范围的比例)
paramsPSO.vMin = -0.2;         % 最小速度限制

%% 3. 运行算法
fprintf('运行遗传算法...\n');
tic;
[bestPosGA, bestFitGA, historyGA] = GeneticAlgorithm(func, paramsGA);
timeGA = toc;
fprintf('遗传算法完成!耗时: %.3f秒\n', timeGA);

fprintf('\n运行粒子群算法...\n');
tic;
[bestPosPSO, bestFitPSO, historyPSO] = ParticleSwarmOptimization(func, paramsPSO);
timePSO = toc;
fprintf('粒子群算法完成!耗时: %.3f秒\n', timePSO);

%% 4. 结果显示
fprintf('\n=== 结果比较 ===\n');
fprintf('%-20s %-20s %-20s\n', '算法', '找到最大值', '误差(%)');
fprintf('%s\n', repmat('-', 60, 1));

errorGA = abs((global_max - bestFitGA) / global_max) * 100;
errorPSO = abs((global_max - bestFitPSO) / global_max) * 100;

fprintf('%-20s %.10f %.2f%%\n', '遗传算法', bestFitGA, errorGA);
fprintf('%-20s %.10f %.2f%%\n', '粒子群算法', bestFitPSO, errorPSO);
fprintf('%-20s %.10f 0.00%%\n', '理论最大值', global_max);

fprintf('\n%-20s %-30s\n', '算法', '最优解位置');
fprintf('%s\n', repmat('-', 60, 1));
fprintf('遗传算法: [');
for i = 1:min(5, dim)
    fprintf('%.6f ', bestPosGA(i));
end
if dim > 5
    fprintf('... ');
end
fprintf(']\n');

fprintf('粒子群算法: [');
for i = 1:min(5, dim)
    fprintf('%.6f ', bestPosPSO(i));
end
if dim > 5
    fprintf('... ');
end
fprintf(']\n');

fprintf('理论最优: [');
for i = 1:min(5, dim)
    fprintf('%.6f ', global_max_pos(i));
end
if dim > 5
    fprintf('... ');
end
fprintf(']\n');

%% 5. 可视化比较
% 5.1 收敛曲线比较
figure('Position', [100, 100, 1400, 800]);

% 收敛曲线
subplot(2, 3, 1);
plot(1:length(historyGA.bestFitness), historyGA.bestFitness, 'b-', 'LineWidth', 2);
hold on;
plot(1:length(historyPSO.bestFitness), historyPSO.bestFitness, 'r-', 'LineWidth', 2);
yline(global_max, 'k--', 'LineWidth', 1.5, 'DisplayName', '理论最大值');
xlabel('迭代次数');
ylabel('函数值');
title('收敛曲线比较');
legend('遗传算法', '粒子群算法', '理论最大值', 'Location', 'best');
grid on;

% 平均适应度
subplot(2, 3, 2);
plot(1:length(historyGA.avgFitness), historyGA.avgFitness, 'b-', 'LineWidth', 2);
hold on;
plot(1:length(historyPSO.avgFitness), historyPSO.avgFitness, 'r-', 'LineWidth', 2);
xlabel('迭代次数');
ylabel('平均函数值');
title('种群平均适应度变化');
legend('遗传算法', '粒子群算法', 'Location', 'best');
grid on;

% 标准差变化
subplot(2, 3, 3);
plot(1:length(historyGA.stdFitness), historyGA.stdFitness, 'b-', 'LineWidth', 2);
hold on;
plot(1:length(historyPSO.stdFitness), historyPSO.stdFitness, 'r-', 'LineWidth', 2);
xlabel('迭代次数');
ylabel('适应度标准差');
title('种群多样性变化');
legend('遗传算法', '粒子群算法', 'Location', 'best');
grid on;

% 5.2 函数曲面可视化(仅适用于2维函数)
if dim == 2
    % 创建网格
    x1 = linspace(bounds(1,1), bounds(1,2), 100);
    x2 = linspace(bounds(2,1), bounds(2,2), 100);
    [X1, X2] = meshgrid(x1, x2);
    
    % 计算函数值
    Z = zeros(size(X1));
    for i = 1:size(X1,1)
        for j = 1:size(X1,2)
            Z(i,j) = func([X1(i,j), X2(i,j)]);
        end
    end
    
    % 等高线图
    subplot(2, 3, 4);
    contourf(X1, X2, Z, 30);
    hold on;
    plot(bestPosGA(1), bestPosGA(2), 'bo', 'MarkerSize', 10, 'LineWidth', 2, ...
        'DisplayName', 'GA最优解');
    plot(bestPosPSO(1), bestPosPSO(2), 'rs', 'MarkerSize', 10, 'LineWidth', 2, ...
        'DisplayName', 'PSO最优解');
    plot(global_max_pos(1), global_max_pos(2), 'k*', 'MarkerSize', 15, 'LineWidth', 2, ...
        'DisplayName', '理论最优');
    xlabel('x_1');
    ylabel('x_2');
    title('函数等高线图及最优解位置');
    legend('Location', 'best');
    colorbar;
    grid on;
    
    % 3D曲面图
    subplot(2, 3, 5);
    surf(X1, X2, Z, 'EdgeColor', 'none', 'FaceAlpha', 0.8);
    hold on;
    plot3(bestPosGA(1), bestPosGA(2), bestFitGA, 'bo', 'MarkerSize', 10, ...
        'LineWidth', 2, 'DisplayName', 'GA最优解');
    plot3(bestPosPSO(1), bestPosPSO(2), bestFitPSO, 'rs', 'MarkerSize', 10, ...
        'LineWidth', 2, 'DisplayName', 'PSO最优解');
    plot3(global_max_pos(1), global_max_pos(2), global_max, 'k*', 'MarkerSize', 15, ...
        'LineWidth', 2, 'DisplayName', '理论最优');
    xlabel('x_1');
    ylabel('x_2');
    zlabel('f(x)');
    title('函数3D曲面图');
    legend('Location', 'best');
    grid on;
    view(45, 30);
end

% 5.3 算法性能统计
subplot(2, 3, 6);
algorithms = {'遗传算法', '粒子群算法'};
best_values = [bestFitGA, bestFitPSO];
times = [timeGA, timePSO];
iterations = [length(historyGA.bestFitness), length(historyPSO.bestFitness)];

yyaxis left;
bar(best_values);
ylabel('找到的最大值');
ylim([min(best_values)*0.99, global_max*1.01]);

yyaxis right;
plot(times, 's-', 'LineWidth', 2, 'MarkerSize', 10);
ylabel('计算时间(秒)');

set(gca, 'XTickLabel', algorithms);
title('算法性能比较');
grid on;

%% 6. 多次运行统计比较
fprintf('\n=== 统计比较(运行%d次) ===\n', 10);
statsGA = run_multiple_trials(@GeneticAlgorithm, func, paramsGA, 10);
statsPSO = run_multiple_trials(@ParticleSwarmOptimization, func, paramsPSO, 10);

fprintf('\n%-15s %-10s %-10s %-10s %-10s\n', ...
    '算法', '均值', '标准差', '最好值', '最差值');
fprintf('%s\n', repmat('-', 55, 1));

fprintf('%-15s %.6f %.6f %.6f %.6f\n', ...
    '遗传算法', statsGA.mean, statsGA.std, statsGA.best, statsGA.worst);

fprintf('%-15s %.6f %.6f %.6f %.6f\n', ...
    '粒子群算法', statsPSO.mean, statsPSO.std, statsPSO.best, statsPSO.worst);

fprintf('理论最大值: %.6f\n', global_max);

%% 7. 保存结果
results = struct();
results.GA = struct('position', bestPosGA, 'fitness', bestFitGA, 'history', historyGA);
results.PSO = struct('position', bestPosPSO, 'fitness', bestFitPSO, 'history', historyPSO);
results.function = struct('name', func_name, 'dim', dim, 'bounds', bounds, ...
    'global_max', global_max, 'global_max_pos', global_max_pos);
results.stats = struct('GA', statsGA, 'PSO', statsPSO);

save('GA_PSO_Comparison.mat', 'results');
fprintf('\n结果已保存到 GA_PSO_Comparison.mat\n');

2. 测试函数定义

function [func, func_name, bounds, dim, global_max, global_max_pos] = ...
    get_test_function(choice)
% 获取测试函数
    
    switch choice
        case 1  % Sphere函数(单峰)
            func = @(x) -sum(x.^2);  % 转换为求最大值问题
            func_name = 'Sphere Function';
            dim = 10;
            bounds = repmat([-5, 5], dim, 1);
            global_max_pos = zeros(1, dim);
            global_max = 0;
            
        case 2  % Rastrigin函数(多峰)
            func = @(x) -(10*dim + sum(x.^2 - 10*cos(2*pi*x)));
            func_name = 'Rastrigin Function';
            dim = 10;
            bounds = repmat([-5.12, 5.12], dim, 1);
            global_max_pos = zeros(1, dim);
            global_max = 0;
            
        case 3  % Ackley函数(多峰)
            func = @(x) -(-20*exp(-0.2*sqrt(mean(x.^2))) - ...
                exp(mean(cos(2*pi*x))) + 20 + exp(1));
            func_name = 'Ackley Function';
            dim = 10;
            bounds = repmat([-32, 32], dim, 1);
            global_max_pos = zeros(1, dim);
            global_max = 0;
            
        case 4  % Rosenbrock函数(病态)
            func = @(x) -sum(100*(x(2:end) - x(1:end-1).^2).^2 + (1 - x(1:end-1)).^2);
            func_name = 'Rosenbrock Function';
            dim = 10;
            bounds = repmat([-2, 2], dim, 1);
            global_max_pos = ones(1, dim);
            global_max = 0;
            
        case 5  % Griewank函数(多峰,高维)
            func = @(x) -(1 + sum(x.^2)/4000 - prod(cos(x./sqrt(1:dim))));
            func_name = 'Griewank Function';
            dim = 10;
            bounds = repmat([-600, 600], dim, 1);
            global_max_pos = zeros(1, dim);
            global_max = 0;
            
        case 6  % Schwefel函数(多峰,欺骗性)
            func = @(x) -418.9829*dim + sum(x.*sin(sqrt(abs(x))));
            func_name = 'Schwefel Function';
            dim = 10;
            bounds = repmat([-500, 500], dim, 1);
            global_max_pos = repmat(420.9687, 1, dim);
            global_max = 0;
            
        case 7  % 自定义函数:复杂多峰函数
            func = @(x) -(abs(sum(sin(x))) + 1) ./ (0.1 + sqrt(sum(x.^2)));
            func_name = 'Custom Complex Function';
            dim = 5;
            bounds = repmat([-10, 10], dim, 1);
            global_max_pos = zeros(1, dim);
            global_max = 10;  % 近似值
            
        otherwise
            error('未知的测试函数选择');
    end
end

3. 遗传算法实现

function [bestPosition, bestFitness, history] = GeneticAlgorithm(func, params)
% 遗传算法实现
    
    % 初始化参数
    popSize = params.popSize;
    maxIter = params.maxIter;
    dim = params.dim;
    bounds = params.bounds;
    verbose = params.verbose;
    
    crossoverProb = params.crossoverProb;
    mutationProb = params.mutationProb;
    selectionMethod = params.selectionMethod;
    crossoverMethod = params.crossoverMethod;
    mutationMethod = params.mutationMethod;
    elitismCount = params.elitismCount;
    
    % 初始化历史记录
    history.bestFitness = zeros(maxIter, 1);
    history.avgFitness = zeros(maxIter, 1);
    history.stdFitness = zeros(maxIter, 1);
    history.bestPosition = zeros(maxIter, dim);
    
    % 1. 初始化种群
    population = initializePopulation(popSize, dim, bounds);
    fitness = evaluatePopulation(population, func);
    
    % 2. 记录初始状态
    [bestFitness, bestIdx] = max(fitness);
    bestPosition = population(bestIdx, :);
    
    history.bestFitness(1) = bestFitness;
    history.avgFitness(1) = mean(fitness);
    history.stdFitness(1) = std(fitness);
    history.bestPosition(1, :) = bestPosition;
    
    % 3. 主迭代循环
    for iter = 1:maxIter
        if verbose && mod(iter, 10) == 0
            fprintf('迭代 %3d: 最佳适应度 = %.10f\n', iter, bestFitness);
        end
        
        % 3.1 选择
        parents = selection(population, fitness, selectionMethod);
        
        % 3.2 交叉
        offspring = crossover(parents, crossoverProb, crossoverMethod, bounds);
        
        % 3.3 变异
        offspring = mutation(offspring, mutationProb, mutationMethod, bounds, iter, maxIter);
        
        % 3.4 精英保留
        [offspring, offspringFitness] = elitism(...
            population, fitness, offspring, elitismCount, func);
        
        % 3.5 更新种群
        population = offspring;
        fitness = offspringFitness;
        
        % 3.6 更新最优解
        [currentBestFitness, currentBestIdx] = max(fitness);
        currentBestPosition = population(currentBestIdx, :);
        
        if currentBestFitness > bestFitness
            bestFitness = currentBestFitness;
            bestPosition = currentBestPosition;
        end
        
        % 3.7 记录历史
        history.bestFitness(iter) = bestFitness;
        history.avgFitness(iter) = mean(fitness);
        history.stdFitness(iter) = std(fitness);
        history.bestPosition(iter, :) = bestPosition;
        
        % 3.8 早停检查(可选)
        if iter > 50 && std(history.bestFitness(iter-49:iter)) < 1e-10
            if verbose
                fprintf('早停在迭代 %d\n', iter);
            end
            break;
        end
    end
    
    % 截断历史记录
    history.bestFitness = history.bestFitness(1:iter);
    history.avgFitness = history.avgFitness(1:iter);
    history.stdFitness = history.stdFitness(1:iter);
    history.bestPosition = history.bestPosition(1:iter, :);
end

function population = initializePopulation(popSize, dim, bounds)
% 初始化种群
    population = zeros(popSize, dim);
    for i = 1:popSize
        for j = 1:dim
            population(i, j) = bounds(j,1) + rand() * (bounds(j,2) - bounds(j,1));
        end
    end
end

function fitness = evaluatePopulation(population, func)
% 评估种群适应度
    popSize = size(population, 1);
    fitness = zeros(popSize, 1);
    
    for i = 1:popSize
        fitness(i) = func(population(i, :));
    end
end

function parents = selection(population, fitness, method)
% 选择操作
    popSize = size(population, 1);
    parents = zeros(popSize, size(population, 2));
    
    switch method
        case 'roulette'
            % 轮盘赌选择
            fitness_pos = fitness - min(fitness) + eps;  % 确保非负
            prob = fitness_pos / sum(fitness_pos);
            cumProb = cumsum(prob);
            
            for i = 1:popSize
                r = rand();
                idx = find(cumProb >= r, 1);
                parents(i, :) = population(idx, :);
            end
            
        case 'tournament'
            % 锦标赛选择
            tournamentSize = 3;
            for i = 1:popSize
                % 随机选择k个个体
                tournamentIdx = randperm(popSize, tournamentSize);
                tournamentFitness = fitness(tournamentIdx);
                
                % 选择最好的一个
                [~, bestIdx] = max(tournamentFitness);
                parents(i, :) = population(tournamentIdx(bestIdx), :);
            end
            
        case 'rank'
            % 排序选择
            [~, sortedIdx] = sort(fitness, 'descend');
            ranks = 1:popSize;
            prob = 2*(popSize - ranks + 1) / (popSize*(popSize+1));
            cumProb = cumsum(prob);
            
            for i = 1:popSize
                r = rand();
                idx = find(cumProb >= r, 1);
                parents(i, :) = population(sortedIdx(idx), :);
            end
    end
end

function offspring = crossover(parents, prob, method, bounds)
% 交叉操作
    popSize = size(parents, 1);
    dim = size(parents, 2);
    offspring = parents;  % 默认直接复制
    
    for i = 1:2:popSize-1
        if rand() < prob
            switch method
                case 'single'
                    % 单点交叉
                    point = randi(dim-1);
                    offspring(i, point+1:end) = parents(i+1, point+1:end);
                    offspring(i+1, point+1:end) = parents(i, point+1:end);
                    
                case 'two'
                    % 两点交叉
                    points = sort(randperm(dim, 2));
                    offspring(i, points(1):points(2)) = parents(i+1, points(1):points(2));
                    offspring(i+1, points(1):points(2)) = parents(i, points(1):points(2));
                    
                case 'blend'
                    % 模拟二进制交叉
                    beta = rand(1, dim);
                    for j = 1:dim
                        if rand() < 0.5
                            beta(j) = (2*rand())^(1/3);
                        else
                            beta(j) = (1/(2*(1-rand())))^(1/3);
                        end
                    end
                    
                    offspring(i, :) = 0.5*((1+beta).*parents(i,:) + (1-beta).*parents(i+1,:));
                    offspring(i+1, :) = 0.5*((1-beta).*parents(i,:) + (1+beta).*parents(i+1,:));
                    
                case 'arithmetic'
                    % 算术交叉
                    alpha = rand();
                    offspring(i, :) = alpha*parents(i,:) + (1-alpha)*parents(i+1,:);
                    offspring(i+1, :) = alpha*parents(i+1,:) + (1-alpha)*parents(i,:);
            end
            
            % 边界检查
            offspring(i, :) = min(max(offspring(i, :), bounds(:,1)'), bounds(:,2)');
            offspring(i+1, :) = min(max(offspring(i+1, :), bounds(:,1)'), bounds(:,2)');
        end
    end
end

function offspring = mutation(offspring, prob, method, bounds, iter, maxIter)
% 变异操作
    popSize = size(offspring, 1);
    dim = size(offspring, 2);
    
    for i = 1:popSize
        if rand() < prob
            switch method
                case 'uniform'
                    % 均匀变异
                    for j = 1:dim
                        if rand() < 1/dim
                            offspring(i, j) = bounds(j,1) + rand()*(bounds(j,2) - bounds(j,1));
                        end
                    end
                    
                case 'gaussian'
                    % 高斯变异
                    for j = 1:dim
                        if rand() < 1/dim
                            sigma = (bounds(j,2) - bounds(j,1)) * (1 - iter/maxIter);
                            mutation = sigma * randn();
                            offspring(i, j) = offspring(i, j) + mutation;
                        end
                    end
                    
                case 'nonUniform'
                    % 非均匀变异
                    for j = 1:dim
                        if rand() < 1/dim
                            r = rand();
                            tau = (bounds(j,2) - bounds(j,1)) * (1 - iter/maxIter)^2;
                            if r < 0.5
                                delta = tau * ((2*r)^(1/(1+iter/maxIter)) - 1);
                            else
                                delta = tau * (1 - (2*(1-r))^(1/(1+iter/maxIter)));
                            end
                            offspring(i, j) = offspring(i, j) + delta;
                        end
                    end
            end
            
            % 边界检查
            offspring(i, :) = min(max(offspring(i, :), bounds(:,1)'), bounds(:,2)');
        end
    end
end

function [newPopulation, newFitness] = elitism(...
    oldPopulation, oldFitness, newPopulation, elitismCount, func)
% 精英保留策略
    [sortedFitness, sortedIdx] = sort(oldFitness, 'descend');
    
    % 保留精英个体
    for i = 1:min(elitismCount, length(sortedIdx))
        newPopulation(i, :) = oldPopulation(sortedIdx(i), :);
    end
    
    % 重新评估适应度
    popSize = size(newPopulation, 1);
    newFitness = zeros(popSize, 1);
    
    for i = 1:popSize
        newFitness(i) = func(newPopulation(i, :));
    end
end

4. 粒子群算法实现

function [bestPosition, bestFitness, history] = ParticleSwarmOptimization(func, params)
% 粒子群优化算法实现
    
    % 初始化参数
    popSize = params.popSize;
    maxIter = params.maxIter;
    dim = params.dim;
    bounds = params.bounds;
    verbose = params.verbose;
    
    wMax = params.wMax;
    wMin = params.wMin;
    c1 = params.c1;
    c2 = params.c2;
    vMax = params.vMax;
    vMin = params.vMin;
    
    % 计算速度限制
    range = bounds(:,2) - bounds(:,1);
    vMaxLimit = vMax * range';
    vMinLimit = vMin * range';
    
    % 初始化历史记录
    history.bestFitness = zeros(maxIter, 1);
    history.avgFitness = zeros(maxIter, 1);
    history.stdFitness = zeros(maxIter, 1);
    history.w = zeros(maxIter, 1);
    history.bestPosition = zeros(maxIter, dim);
    
    % 1. 初始化粒子群
    [positions, velocities, personalBestPositions, personalBestFitness] = ...
        initializePSO(popSize, dim, bounds, func);
    
    % 2. 初始化全局最优
    [globalBestFitness, globalBestIdx] = max(personalBestFitness);
    globalBestPosition = personalBestPositions(globalBestIdx, :);
    
    history.bestFitness(1) = globalBestFitness;
    history.avgFitness(1) = mean(personalBestFitness);
    history.stdFitness(1) = std(personalBestFitness);
    history.w(1) = wMax;
    history.bestPosition(1, :) = globalBestPosition;
    
    % 3. 主迭代循环
    for iter = 1:maxIter
        % 3.1 自适应调整参数
        w = wMax - (wMax - wMin) * iter / maxIter;  % 线性递减惯性权重
        history.w(iter) = w;
        
        % 3.2 更新每个粒子
        for i = 1:popSize
            % 更新速度
            r1 = rand(1, dim);
            r2 = rand(1, dim);
            
            velocities(i, :) = w * velocities(i, :) + ...
                c1 * r1 .* (personalBestPositions(i, :) - positions(i, :)) + ...
                c2 * r2 .* (globalBestPosition - positions(i, :));
            
            % 速度限制
            velocities(i, :) = max(min(velocities(i, :), vMaxLimit), vMinLimit);
            
            % 更新位置
            positions(i, :) = positions(i, :) + velocities(i, :);
            
            % 边界处理
            for j = 1:dim
                if positions(i, j) < bounds(j,1)
                    positions(i, j) = bounds(j,1);
                    velocities(i, j) = -0.5 * velocities(i, j);  % 反弹
                elseif positions(i, j) > bounds(j,2)
                    positions(i, j) = bounds(j,2);
                    velocities(i, j) = -0.5 * velocities(i, j);  % 反弹
                end
            end
            
            % 计算当前适应度
            currentFitness = func(positions(i, :));
            
            % 更新个体最优
            if currentFitness > personalBestFitness(i)
                personalBestFitness(i) = currentFitness;
                personalBestPositions(i, :) = positions(i, :);
                
                % 更新全局最优
                if currentFitness > globalBestFitness
                    globalBestFitness = currentFitness;
                    globalBestPosition = positions(i, :);
                end
            end
        end
        
        % 3.3 记录历史信息
        history.bestFitness(iter) = globalBestFitness;
        history.avgFitness(iter) = mean(personalBestFitness);
        history.stdFitness(iter) = std(personalBestFitness);
        history.bestPosition(iter, :) = globalBestPosition;
        
        % 3.4 显示进度
        if verbose && mod(iter, 10) == 0
            fprintf('迭代 %3d: 最佳适应度 = %.10f\n', iter, globalBestFitness);
        end
        
        % 3.5 早停检查
        if iter > 50 && std(history.bestFitness(iter-49:iter)) < 1e-10
            if verbose
                fprintf('早停在迭代 %d\n', iter);
            end
            break;
        end
    end
    
    % 4. 返回结果
    bestPosition = globalBestPosition;
    bestFitness = globalBestFitness;
    
    % 截断历史记录
    history.bestFitness = history.bestFitness(1:iter);
    history.avgFitness = history.avgFitness(1:iter);
    history.stdFitness = history.stdFitness(1:iter);
    history.w = history.w(1:iter);
    history.bestPosition = history.bestPosition(1:iter, :);
end

function [positions, velocities, personalBestPositions, personalBestFitness] = ...
    initializePSO(popSize, dim, bounds, func)
% 初始化粒子群
    
    % 初始化位置
    positions = zeros(popSize, dim);
    for i = 1:popSize
        for j = 1:dim
            positions(i, j) = bounds(j,1) + rand() * (bounds(j,2) - bounds(j,1));
        end
    end
    
    % 初始化速度
    range = bounds(:,2) - bounds(:,1);
    velocities = zeros(popSize, dim);
    for i = 1:popSize
        for j = 1:dim
            velocities(i, j) = -0.1 * range(j) + 0.2 * range(j) * rand();
        end
    end
    
    % 初始化个体最优
    personalBestPositions = positions;
    personalBestFitness = zeros(popSize, 1);
    
    for i = 1:popSize
        personalBestFitness(i) = func(positions(i, :));
    end
end

5. 辅助函数和性能评估

%% 辅助函数
function stats = run_multiple_trials(algorithm_func, func, params, nTrials)
% 多次运行算法进行统计
    
    bestValues = zeros(nTrials, 1);
    times = zeros(nTrials, 1);
    
    for trial = 1:nTrials
        fprintf('运行 %d/%d...\n', trial, nTrials);
        
        % 运行算法
        params.verbose = false;  % 关闭详细输出
        tic;
        [~, bestFit, ~] = algorithm_func(func, params);
        elapsedTime = toc;
        
        bestValues(trial) = bestFit;
        times(trial) = elapsedTime;
    end
    
    % 计算统计量
    stats = struct();
    stats.mean = mean(bestValues);
    stats.std = std(bestValues);
    stats.best = max(bestValues);
    stats.worst = min(bestValues);
    stats.times = times;
    stats.values = bestValues;
end

%% 算法性能分析函数
function analyze_algorithm_performance()
% 分析算法在不同维度下的性能
    
    % 测试不同维度的Sphere函数
    dims = [2, 5, 10, 20, 30, 50];
    nRuns = 10;
    
    resultsGA = cell(length(dims), 1);
    resultsPSO = cell(length(dims), 1);
    
    fprintf('\n=== 不同维度下的算法性能分析 ===\n');
    fprintf('%-6s %-15s %-15s %-15s %-15s\n', ...
        '维度', '算法', '平均适应度', '标准差', '平均时间(秒)');
    fprintf('%s\n', repmat('-', 70, 1));
    
    for i = 1:length(dims)
        dim = dims(i);
        
        % 定义Sphere函数
        func = @(x) -sum(x.^2);
        bounds = repmat([-5, 5], dim, 1);
        
        % 遗传算法参数
        paramsGA = struct();
        paramsGA.popSize = 50;
        paramsGA.maxIter = 100;
        paramsGA.dim = dim;
        paramsGA.bounds = bounds;
        paramsGA.verbose = false;
        paramsGA.crossoverProb = 0.8;
        paramsGA.mutationProb = 0.1;
        paramsGA.selectionMethod = 'tournament';
        paramsGA.crossoverMethod = 'blend';
        paramsGA.mutationMethod = 'gaussian';
        paramsGA.elitismCount = 2;
        
        % 粒子群算法参数
        paramsPSO = struct();
        paramsPSO.popSize = 50;
        paramsPSO.maxIter = 100;
        paramsPSO.dim = dim;
        paramsPSO.bounds = bounds;
        paramsPSO.verbose = false;
        paramsPSO.wMax = 0.9;
        paramsPSO.wMin = 0.4;
        paramsPSO.c1 = 2.0;
        paramsPSO.c2 = 2.0;
        paramsPSO.vMax = 0.2;
        paramsPSO.vMin = -0.2;
        
        % 运行多次
        statsGA = run_multiple_trials(@GeneticAlgorithm, func, paramsGA, nRuns);
        statsPSO = run_multiple_trials(@ParticleSwarmOptimization, func, paramsPSO, nRuns);
        
        % 保存结果
        resultsGA{i} = statsGA;
        resultsPSO{i} = statsPSO;
        
        % 显示结果
        fprintf('%-6d %-15s %-15.6f %-15.6f %-15.3f\n', ...
            dim, '遗传算法', statsGA.mean, statsGA.std, mean(statsGA.times));
        fprintf('%-6d %-15s %-15.6f %-15.6f %-15.3f\n', ...
            dim, '粒子群算法', statsPSO.mean, statsPSO.std, mean(statsPSO.times));
        fprintf('\n');
    end
    
    % 可视化
    figure('Position', [100, 100, 1200, 500]);
    
    % 适应度随维度变化
    subplot(1, 3, 1);
    ga_means = cellfun(@(x) -x.mean, resultsGA);  % 转换为正值
    pso_means = cellfun(@(x) -x.mean, resultsPSO);
    
    plot(dims, ga_means, 'bo-', 'LineWidth', 2, 'MarkerSize', 8);
    hold on;
    plot(dims, pso_means, 'rs-', 'LineWidth', 2, 'MarkerSize', 8);
    plot(dims, zeros(size(dims)), 'k--', 'LineWidth', 1.5);
    xlabel('维度');
    ylabel('平均适应度(正值)');
    title('适应度随维度变化');
    legend('遗传算法', '粒子群算法', '理论最优', 'Location', 'best');
    grid on;
    
    % 计算时间随维度变化
    subplot(1, 3, 2);
    ga_times = cellfun(@(x) mean(x.times), resultsGA);
    pso_times = cellfun(@(x) mean(x.times), resultsPSO);
    
    plot(dims, ga_times, 'bo-', 'LineWidth', 2, 'MarkerSize', 8);
    hold on;
    plot(dims, pso_times, 'rs-', 'LineWidth', 2, 'MarkerSize', 8);
    xlabel('维度');
    ylabel('平均计算时间(秒)');
    title('计算时间随维度变化');
    legend('遗传算法', '粒子群算法', 'Location', 'best');
    grid on;
    
    % 成功率(达到理论最优99%)
    subplot(1, 3, 3);
    ga_success = zeros(length(dims), 1);
    pso_success = zeros(length(dims), 1);
    
    for i = 1:length(dims)
        ga_success(i) = sum(resultsGA{i}.values > -0.01) / nRuns * 100;
        pso_success(i) = sum(resultsPSO{i}.values > -0.01) / nRuns * 100;
    end
    
    bar([ga_success, pso_success]);
    xlabel('维度索引');
    ylabel('成功率(%)');
    title('成功率比较');
    legend('遗传算法', '粒子群算法', 'Location', 'best');
    grid on;
    set(gca, 'XTickLabel', dims);
end

%% 混合算法(GA-PSO)
function [bestPosition, bestFitness, history] = GA_PSO_Hybrid(func, params)
% 遗传算法-粒子群混合算法
    
    % 参数
    popSize = params.popSize;
    maxIter = params.maxIter;
    dim = params.dim;
    bounds = params.bounds;
    verbose = params.verbose;
    
    % 分割种群
    nGA = floor(popSize * 0.5);
    nPSO = popSize - nGA;
    
    % 初始化历史记录
    history.bestFitness = zeros(maxIter, 1);
    history.avgFitness = zeros(maxIter, 1);
    
    % 1. 初始化两个子种群
    % GA种群
    populationGA = initializePopulation(nGA, dim, bounds);
    fitnessGA = evaluatePopulation(populationGA, func);
    
    % PSO种群
    [positionsPSO, velocitiesPSO, personalBestPositions, personalBestFitness] = ...
        initializePSO(nPSO, dim, bounds, func);
    
    % 2. 初始全局最优
    [bestFitnessGA, bestIdxGA] = max(fitnessGA);
    [bestFitnessPSO, bestIdxPSO] = max(personalBestFitness);
    
    if bestFitnessGA > bestFitnessPSO
        globalBestFitness = bestFitnessGA;
        globalBestPosition = populationGA(bestIdxGA, :);
    else
        globalBestFitness = bestFitnessPSO;
        globalBestPosition = personalBestPositions(bestIdxPSO, :);
    end
    
    % 3. 主迭代循环
    for iter = 1:maxIter
        % 3.1 运行GA迭代
        % 选择
        parentsGA = selection(populationGA, fitnessGA, 'tournament');
        
        % 交叉
        offspringGA = crossover(parentsGA, 0.8, 'blend', bounds);
        
        % 变异
        offspringGA = mutation(offspringGA, 0.1, 'gaussian', bounds, iter, maxIter);
        
        % 评估
        fitnessGA = evaluatePopulation(offspringGA, func);
        populationGA = offspringGA;
        
        % 3.2 运行PSO迭代
        w = 0.9 - (0.9 - 0.4) * iter / maxIter;
        
        for i = 1:nPSO
            % 更新速度
            r1 = rand(1, dim);
            r2 = rand(1, dim);
            
            velocitiesPSO(i, :) = w * velocitiesPSO(i, :) + ...
                2.0 * r1 .* (personalBestPositions(i, :) - positionsPSO(i, :)) + ...
                2.0 * r2 .* (globalBestPosition - positionsPSO(i, :));
            
            % 更新位置
            positionsPSO(i, :) = positionsPSO(i, :) + velocitiesPSO(i, :);
            
            % 边界处理
            positionsPSO(i, :) = min(max(positionsPSO(i, :), bounds(:,1)'), bounds(:,2)');
            
            % 计算适应度
            currentFitness = func(positionsPSO(i, :));
            
            % 更新个体最优
            if currentFitness > personalBestFitness(i)
                personalBestFitness(i) = currentFitness;
                personalBestPositions(i, :) = positionsPSO(i, :);
            end
        end
        
        % 3.3 信息交换(迁移)
        if mod(iter, 10) == 0
            % 选择GA中最好的个体替换PSO中最差的个体
            [~, gaBestIdx] = max(fitnessGA);
            [~, psoWorstIdx] = min(personalBestFitness);
            
            positionsPSO(psoWorstIdx, :) = populationGA(gaBestIdx, :);
            personalBestPositions(psoWorstIdx, :) = populationGA(gaBestIdx, :);
            personalBestFitness(psoWorstIdx) = fitnessGA(gaBestIdx);
            
            % 选择PSO中最好的个体替换GA中最差的个体
            [~, psoBestIdx] = max(personalBestFitness);
            [~, gaWorstIdx] = min(fitnessGA);
            
            populationGA(gaWorstIdx, :) = personalBestPositions(psoBestIdx, :);
            fitnessGA(gaWorstIdx) = personalBestFitness(psoBestIdx);
        end
        
        % 3.4 更新全局最优
        [currentBestFitnessGA, currentBestIdxGA] = max(fitnessGA);
        [currentBestFitnessPSO, currentBestIdxPSO] = max(personalBestFitness);
        
        if currentBestFitnessGA > currentBestFitnessPSO
            currentBestFitness = currentBestFitnessGA;
            currentBestPosition = populationGA(currentBestIdxGA, :);
        else
            currentBestFitness = currentBestFitnessPSO;
            currentBestPosition = personalBestPositions(currentBestIdxPSO, :);
        end
        
        if currentBestFitness > globalBestFitness
            globalBestFitness = currentBestFitness;
            globalBestPosition = currentBestPosition;
        end
        
        % 3.5 记录历史
        history.bestFitness(iter) = globalBestFitness;
        history.avgFitness(iter) = (mean(fitnessGA) * nGA + ...
            mean(personalBestFitness) * nPSO) / popSize;
        
        % 3.6 显示进度
        if verbose && mod(iter, 10) == 0
            fprintf('迭代 %3d: 最佳适应度 = %.10f\n', iter, globalBestFitness);
        end
    end
    
    % 4. 返回结果
    bestPosition = globalBestPosition;
    bestFitness = globalBestFitness;
end

参考代码 遗传算法和粒子群算法求解非线性函数最大值问题 www.3dddown.com/cna/97949.html

6. 算法比较总结

遗传算法特点:

  1. 优点

    • 全局搜索能力强,适合多峰函数
    • 对初始值不敏感
    • 并行性好,适合大规模优化
    • 可以处理离散和连续变量
  2. 缺点

    • 收敛速度较慢
    • 参数调节复杂
    • 局部搜索能力较弱

粒子群算法特点:

  1. 优点

    • 收敛速度快
    • 参数少,易于实现
    • 局部搜索能力强
    • 适合连续优化问题
  2. 缺点

    • 容易陷入局部最优
    • 对初始值敏感
    • 处理离散问题较困难

使用建议:

  1. 选择GA的情况

    • 问题高度多峰
    • 需要全局最优解
    • 有充足的计算时间
    • 问题包含离散变量
  2. 选择PSO的情况

    • 问题相对简单
    • 需要快速收敛
    • 连续优化问题
    • 计算资源有限
  3. 混合策略

    • 前期使用GA进行全局探索
    • 后期使用PSO进行局部开发
    • 结合两者优点,提高整体性能
posted @ 2026-01-08 10:35  bqyfa66984  阅读(4)  评论(0)    收藏  举报