遗传算法求解最优值
遗传算法求解最优值 - 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. 遗传算法基本流程
遗传算法模拟自然选择和遗传机制,主要包含以下步骤:
- 初始化种群:在搜索空间内随机生成一组初始解(个体)
- 适应度评估:计算每个个体的适应度值(目标函数值)
- 选择操作:根据适应度选择优秀个体作为父代
- 交叉操作:通过父代个体生成新的子代个体
- 变异操作:以一定概率改变个体基因
- 精英保留:保留每代最优个体直接进入下一代
- 终止条件:达到最大迭代次数或满足收敛条件
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. 可视化功能
代码提供了丰富的可视化功能:
- 3D函数曲面图:显示目标函数曲面和种群分布
- 等高线图:显示函数轮廓和种群位置
- 收敛曲线:显示最佳适应度和平均适应度的进化过程
- 实时更新:每5代更新一次可视化
- 最终结果分析:显示收敛曲线和优化结果
参考代码 遗传算法计算最优值 www.youwenfan.com/contentcnd/96376.html
算法特点与优势
-
自适应变异:
- 使用非均匀变异策略
- 早期大范围探索,后期精细搜索
- 变异幅度随代数增加而减小
-
精英保留:
- 保留每代最优个体
- 防止优秀解丢失
- 加速收敛过程
-
高效选择机制:
- 锦标赛选择平衡选择压力
- 避免超级个体主导种群
- 保持种群多样性
-
鲁棒交叉操作:
- 模拟二进制交叉(SBX)
- 产生多样化的子代
- 保持种群多样性
浙公网安备 33010602011771号