遗传算法求解最优值

遗传算法求解最优值 - MATLAB实现

遗传算法(Genetic Algorithm, GA)MATLAB实现,用于求解函数最优值。包含了遗传算法的所有核心组件

% 遗传算法求解最优值
% 作者: MATLAB助手
% 日期: 2025-08-15

function genetic_algorithm_optimization()
    % 清空工作区
    clc;
    close all;
    clear;
    
    %% 1. 参数设置
    % 优化问题定义
    problem.fitness_func = @(x) 20 + x(1).^2 + x(2).^2 - 10*(cos(2*pi*x(1)) + cos(2*pi*x(2))); % Rastrigin函数
    problem.nvars = 2;        % 变量个数
    problem.lb = [-5, -5];    % 变量下界
    problem.ub = [5, 5];      % 变量上界
    
    % 遗传算法参数
    ga_params.pop_size = 50;      % 种群大小
    ga_params.max_generations = 100; % 最大迭代次数
    ga_params.crossover_rate = 0.8; % 交叉概率
    ga_params.mutation_rate = 0.1; % 变异概率
    ga_params.elite_count = 2;    % 精英个体数量
    ga_params.tournament_size = 3; % 锦标赛选择大小
    
    % 显示设置
    display_params.plot_interval = 5; % 绘图间隔(代)
    display_params.animate = true;    % 是否开启动画
    
    %% 2. 初始化种群
    population = initialize_population(ga_params, problem);
    
    % 评估初始种群
    fitness = evaluate_population(population, problem);
    
    % 存储最佳解历史
    best_fitness_history = zeros(1, ga_params.max_generations);
    avg_fitness_history = zeros(1, ga_params.max_generations);
    best_individual_history = zeros(ga_params.max_generations, problem.nvars);
    
    %% 3. 创建可视化
    fig = create_figure(problem);
    
    %% 4. 遗传算法主循环
    for gen = 1:ga_params.max_generations
        % 选择操作
        parents = selection(population, fitness, ga_params);
        
        % 交叉操作
        offspring = crossover(parents, ga_params, problem);
        
        % 变异操作
        offspring = mutation(offspring, ga_params, problem, gen, ga_params.max_generations);
        
        % 合并父代和子代
        combined_pop = [population; offspring];
        combined_fitness = [fitness; evaluate_population(offspring, problem)];
        
        % 精英选择
        [population, fitness] = elite_selection(combined_pop, combined_fitness, ga_params);
        
        % 记录统计信息
        [best_fitness, best_idx] = min(fitness);
        best_individual = population(best_idx, :);
        
        best_fitness_history(gen) = best_fitness;
        avg_fitness_history(gen) = mean(fitness);
        best_individual_history(gen, :) = best_individual;
        
        % 显示当前代信息
        fprintf('代数: %3d | 最佳适应度: %.6f | 平均适应度: %.6f | 最佳解: [', ...
                gen, best_fitness, avg_fitness_history(gen));
        fprintf('%.4f ', best_individual);
        fprintf(']\n');
        
        % 定期更新可视化
        if mod(gen, display_params.plot_interval) == 0 || gen == 1 || gen == ga_params.max_generations
            update_visualization(fig, population, fitness, problem, gen, ...
                                 best_fitness_history, avg_fitness_history, ...
                                 display_params.animate);
            drawnow;
        end
    end
    
    %% 5. 结果分析
    [global_best_fitness, global_best_idx] = min(best_fitness_history);
    global_best_individual = best_individual_history(global_best_idx, :);
    
    fprintf('\n===== 优化结果 =====\n');
    fprintf('最佳适应度: %.6f\n', global_best_fitness);
    fprintf('最佳解: [');
    fprintf('%.6f ', global_best_individual);
    fprintf(']\n');
    fprintf('函数最小值: %.6f\n', problem.fitness_func(global_best_individual));
    fprintf('====================\n');
    
    % 绘制收敛曲线
    plot_convergence(best_fitness_history, avg_fitness_history);
end

%% 辅助函数: 初始化种群
function pop = initialize_population(ga_params, problem)
    pop = zeros(ga_params.pop_size, problem.nvars);
    for i = 1:problem.nvars
        pop(:, i) = problem.lb(i) + (problem.ub(i) - problem.lb(i)) * rand(ga_params.pop_size, 1);
    end
end

%% 辅助函数: 评估种群适应度
function fitness = evaluate_population(pop, problem)
    pop_size = size(pop, 1);
    fitness = zeros(pop_size, 1);
    for i = 1:pop_size
        fitness(i) = problem.fitness_func(pop(i, :));
    end
end

%% 辅助函数: 选择操作 (锦标赛选择)
function parents = selection(pop, fitness, ga_params)
    pop_size = size(pop, 1);
    parents = zeros(pop_size, size(pop, 2));
    
    for i = 1:pop_size
        % 随机选择锦标赛参与者
        tournament_indices = randperm(pop_size, ga_params.tournament_size);
        tournament_fitness = fitness(tournament_indices);
        
        % 选择适应度最好的个体
        [~, best_idx] = min(tournament_fitness);
        parents(i, :) = pop(tournament_indices(best_idx), :);
    end
end

%% 辅助函数: 交叉操作 (模拟二进制交叉)
function offspring = crossover(parents, ga_params, problem)
    pop_size = size(parents, 1);
    offspring = zeros(pop_size, size(parents, 2));
    
    for i = 1:2:pop_size
        parent1 = parents(i, :);
        parent2 = parents(i+1, :);
        
        if rand() < ga_params.crossover_rate
            % 执行交叉
            for j = 1:length(parent1)
                u = rand();
                if u <= 0.5
                    beta = (2*u)^(1/21); % 分布指数
                else
                    beta = (1/(2*(1-u)))^(1/21);
                end
                
                offspring(i, j) = 0.5*((1+beta)*parent1(j) + (1-beta)*parent2(j));
                offspring(i+1, j) = 0.5*((1-beta)*parent1(j) + (1+beta)*parent2(j));
            end
        else
            % 不交叉,直接复制
            offspring(i, :) = parent1;
            offspring(i+1, :) = parent2;
        end
    end
end

%% 辅助函数: 变异操作 (非均匀变异)
function offspring = mutation(offspring, ga_params, problem, gen, max_gen)
    [pop_size, nvars] = size(offspring);
    
    for i = 1:pop_size
        for j = 1:nvars
            if rand() < ga_params.mutation_rate
                % 非均匀变异
                tau = (1 - gen/max_gen)^5;
                if rand() < 0.5
                    delta = (problem.ub(j) - offspring(i, j)) * (1 - rand()^tau);
                else
                    delta = (offspring(i, j) - problem.lb(j)) * (1 - rand()^tau);
                end
                
                if rand() < 0.5
                    offspring(i, j) = offspring(i, j) + delta;
                else
                    offspring(i, j) = offspring(i, j) - delta;
                end
                
                % 边界检查
                offspring(i, j) = min(max(offspring(i, j), problem.lb(j)), problem.ub(j));
            end
        end
    end
end

%% 辅助函数: 精英选择
function [new_pop, new_fitness] = elite_selection(pop, fitness, ga_params)
    % 按适应度排序
    [sorted_fitness, sorted_idx] = sort(fitness);
    
    % 保留精英个体
    elite_indices = sorted_idx(1:ga_params.elite_count);
    elite_pop = pop(elite_indices, :);
    elite_fitness = sorted_fitness(1:ga_params.elite_count);
    
    % 选择剩余个体
    remaining_pop = pop(sorted_idx(ga_params.elite_count+1:end), :);
    remaining_fitness = sorted_fitness(ga_params.elite_count+1:end);
    
    % 轮盘赌选择
    prob = 1./(remaining_fitness - min(remaining_fitness) + 1e-6);
    prob = prob / sum(prob);
    cum_prob = cumsum(prob);
    
    selected_indices = zeros(1, ga_params.pop_size - ga_params.elite_count);
    for i = 1:(ga_params.pop_size - ga_params.elite_count)
        r = rand();
        idx = find(cum_prob >= r, 1);
        selected_indices(i) = idx;
    end
    
    % 创建新种群
    new_pop = [elite_pop; remaining_pop(selected_indices, :)];
    new_fitness = [elite_fitness; remaining_fitness(selected_indices)];
end

%% 辅助函数: 创建可视化界面
function fig = create_figure(problem)
    fig = figure('Name', '遗传算法优化过程', ...
                 'Position', [100, 100, 1200, 800], ...
                 'Color', [0.95, 0.95, 0.95]);
    
    % 创建函数曲面图
    subplot(2, 2, [1, 3]);
    [X, Y] = meshgrid(linspace(problem.lb(1), problem.ub(1), 100), ...
                      linspace(problem.lb(2), problem.ub(2), 100));
    Z = zeros(size(X));
    for i = 1:size(X, 1)
        for j = 1:size(X, 2)
            Z(i, j) = problem.fitness_func([X(i, j), Y(i, j)]);
        end
    end
    
    surf(X, Y, Z, 'EdgeColor', 'none', 'FaceAlpha', 0.7);
    hold on;
    scatter3(0, 0, problem.fitness_func([0, 0]), 100, 'r', 'filled'); % 理论最优解
    title('目标函数曲面与种群分布');
    xlabel('x1');
    ylabel('x2');
    zlabel('f(x)');
    colormap(jet);
    colorbar;
    view(-45, 30);
    grid on;
    
    % 创建种群分布图
    subplot(2, 2, 2);
    contourf(X, Y, Z, 50);
    hold on;
    plot(0, 0, 'r*', 'MarkerSize', 15); % 理论最优解
    title('种群分布 (等高线图)');
    xlabel('x1');
    ylabel('x2');
    colorbar;
    axis square;
    
    % 创建收敛曲线图
    subplot(2, 2, 4);
    title('收敛曲线');
    xlabel('代数');
    ylabel('适应度值');
    grid on;
    hold on;
    
    % 添加信息面板
    annotation('textbox', [0.15, 0.02, 0.7, 0.06], ...
               'String', '遗传算法优化过程可视化', ...
               'FitBoxToText', 'on', ...
               'BackgroundColor', [0.9, 0.9, 0.9], ...
               'EdgeColor', [0.6, 0.6, 0.6], ...
               'FontSize', 12, ...
               'FontWeight', 'bold', ...
               'HorizontalAlignment', 'center');
end

%% 辅助函数: 更新可视化
function update_visualization(fig, population, fitness, problem, gen, ...
                              best_history, avg_history, animate)
    % 获取图形对象
    figure(fig);
    
    % 更新曲面图上的种群点
    subplot(2, 2, [1, 3]);
    if gen == 1
        % 首次绘制
        pop_plot = scatter3(population(:, 1), population(:, 2), ...
                           fitness, 50, 'k', 'filled');
    else
        % 更新现有图形
        pop_plot = findobj(gca, 'Type', 'scatter', 'Tag', 'population');
        if isempty(pop_plot)
            pop_plot = scatter3(population(:, 1), population(:, 2), ...
                               fitness, 50, 'k', 'filled', 'Tag', 'population');
        else
            set(pop_plot, 'XData', population(:, 1), ...
                          'YData', population(:, 2), ...
                          'ZData', fitness);
        end
    end
    title(sprintf('目标函数曲面与种群分布 (代数: %d)', gen));
    
    % 更新等高线图上的种群点
    subplot(2, 2, 2);
    if gen == 1
        contour_pop = scatter(population(:, 1), population(:, 2), ...
                             50, 'k', 'filled');
    else
        contour_pop = findobj(gca, 'Type', 'scatter', 'Tag', 'contour_population');
        if isempty(contour_pop)
            contour_pop = scatter(population(:, 1), population(:, 2), ...
                                 50, 'k', 'filled', 'Tag', 'contour_population');
        else
            set(contour_pop, 'XData', population(:, 1), ...
                             'YData', population(:, 2));
        end
    end
    
    % 更新收敛曲线
    subplot(2, 2, 4);
    if gen == 1
        best_plot = plot(1:gen, best_history(1:gen), 'r-', 'LineWidth', 2, ...
                         'DisplayName', '最佳适应度');
        avg_plot = plot(1:gen, avg_history(1:gen), 'b--', 'LineWidth', 2, ...
                        'DisplayName', '平均适应度');
        legend('Location', 'best');
    else
        best_plot = findobj(gca, 'Type', 'line', 'Color', 'r');
        avg_plot = findobj(gca, 'Type', 'line', 'Color', 'b');
        
        set(best_plot, 'XData', 1:gen, 'YData', best_history(1:gen));
        set(avg_plot, 'XData', 1:gen, 'YData', avg_history(1:gen));
    end
    title(sprintf('收敛曲线 (当前最佳: %.6f)', best_history(gen)));
    xlim([1, max(gen+5, 10)]);
    
    % 添加动画效果
    if animate && gen > 1
        drawnow;
        pause(0.05);
    end
end

%% 辅助函数: 绘制收敛曲线
function plot_convergence(best_history, avg_history)
    figure('Name', '遗传算法收敛曲线', ...
           'Position', [200, 200, 800, 600], ...
           'Color', 'white');
    
    plot(best_history, 'r-', 'LineWidth', 2, 'DisplayName', '最佳适应度');
    hold on;
    plot(avg_history, 'b--', 'LineWidth', 2, 'DisplayName', '平均适应度');
    hold off;
    
    title('遗传算法收敛曲线');
    xlabel('代数');
    ylabel('适应度值');
    legend('Location', 'best');
    grid on;
    
    % 添加标注
    [min_best, min_idx] = min(best_history);
    line([min_idx, min_idx], ylim, 'Color', 'k', 'LineStyle', ':', 'LineWidth', 1);
    text(min_idx, min_best, sprintf(' 最小值: %.6f', min_best), ...
         'VerticalAlignment', 'top');
    
    % 添加信息
    convergence_rate = (best_history(1) - best_history(end)) / best_history(1) * 100;
    annotation('textbox', [0.15, 0.15, 0.7, 0.1], ...
               'String', sprintf('收敛率: %.2f%% | 初始值: %.4f | 最终值: %.6f', ...
               convergence_rate, best_history(1), best_history(end)), ...
               'FitBoxToText', 'on', ...
               'BackgroundColor', [0.95, 0.95, 0.95], ...
               'EdgeColor', [0.7, 0.7, 0.7], ...
               'FontSize', 12);
end

算法原理与实现说明

1. 遗传算法基本流程

遗传算法模拟自然选择和遗传机制,主要包含以下步骤:

  1. 初始化种群:在搜索空间内随机生成一组初始解(个体)
  2. 适应度评估:计算每个个体的适应度值(目标函数值)
  3. 选择操作:根据适应度选择优秀个体作为父代
  4. 交叉操作:通过父代个体生成新的子代个体
  5. 变异操作:以一定概率改变个体基因
  6. 精英保留:保留每代最优个体直接进入下一代
  7. 终止条件:达到最大迭代次数或满足收敛条件

2. 关键组件实现

选择操作 - 锦标赛选择

function parents = selection(pop, fitness, ga_params)
    for i = 1:pop_size
        % 随机选择锦标赛参与者
        tournament_indices = randperm(pop_size, ga_params.tournament_size);
        % 选择适应度最好的个体
        [~, best_idx] = min(fitness(tournament_indices));
        parents(i, :) = pop(tournament_indices(best_idx), :);
    end
end

交叉操作 - 模拟二进制交叉(SBX)

function offspring = crossover(parents, ga_params, problem)
    for i = 1:2:pop_size
        if rand() < ga_params.crossover_rate
            % 执行交叉
            for j = 1:length(parent1)
                u = rand();
                if u <= 0.5
                    beta = (2*u)^(1/21); % 分布指数
                else
                    beta = (1/(2*(1-u)))^(1/21);
                end
                % 生成子代
                offspring(i, j) = 0.5*((1+beta)*parent1(j) + (1-beta)*parent2(j));
            end
        end
    end
end

变异操作 - 非均匀变异

function offspring = mutation(offspring, ga_params, problem, gen, max_gen)
    for i = 1:pop_size
        for j = 1:nvars
            if rand() < ga_params.mutation_rate
                % 非均匀变异
                tau = (1 - gen/max_gen)^5;
                % 计算变异量
                delta = (problem.ub(j) - offspring(i, j)) * (1 - rand()^tau);
                % 应用变异
                offspring(i, j) = offspring(i, j) + delta;
            end
        end
    end
end

精英保留策略

function [new_pop, new_fitness] = elite_selection(pop, fitness, ga_params)
    % 按适应度排序
    [sorted_fitness, sorted_idx] = sort(fitness);
    % 保留精英个体
    elite_pop = pop(sorted_idx(1:ga_params.elite_count), :);
    % 轮盘赌选择剩余个体
    new_pop = [elite_pop; remaining_pop(selected_indices, :)];
end

3. 测试函数 - Rastrigin函数

本实现使用Rastrigin函数作为测试函数:

problem.fitness_func = @(x) 20 + x(1).^2 + x(2).^2 - 10*(cos(2*pi*x(1)) + cos(2*pi*x(2)));

该函数具有以下特点:

  • 全局最小值在(0,0)处,函数值为0
  • 包含大量局部极小值(在2D情况下有约50个局部极小值)
  • 是测试优化算法性能的标准函数之一

4. 可视化功能

代码提供了丰富的可视化功能:

  1. 3D函数曲面图:显示目标函数曲面和种群分布
  2. 等高线图:显示函数轮廓和种群位置
  3. 收敛曲线:显示最佳适应度和平均适应度的进化过程
  4. 实时更新:每5代更新一次可视化
  5. 最终结果分析:显示收敛曲线和优化结果

参考代码 遗传算法计算最优值 www.youwenfan.com/contentcnd/96376.html

算法特点与优势

  1. 自适应变异

    • 使用非均匀变异策略
    • 早期大范围探索,后期精细搜索
    • 变异幅度随代数增加而减小
  2. 精英保留

    • 保留每代最优个体
    • 防止优秀解丢失
    • 加速收敛过程
  3. 高效选择机制

    • 锦标赛选择平衡选择压力
    • 避免超级个体主导种群
    • 保持种群多样性
  4. 鲁棒交叉操作

    • 模拟二进制交叉(SBX)
    • 产生多样化的子代
    • 保持种群多样性
posted @ 2025-08-19 15:58  alloutlove  阅读(19)  评论(0)    收藏  举报