遗传算法应用-- 栅格法机器人路径规划

文章目录

  • 一、遗传算法
    • 1.1 编码与解码
    • 1.2 选择算子-轮盘赌法
    • 1.3 交叉算子
    • 1.4 变异算子
    • 1.5 遗传算法流程
    • 1.6 基于遗传算法的栅格法机器人路径规划
  • 二、采用模拟退火算法改善适应度函数

一、遗传算法

遗传算法 (Genetic AIgorithm, 简称 GA)起源于对生物系统所进行的计算机模拟研究,是一种随机全局搜索优化方法,它模拟了自然选择和遗传中发生的复制、交叉 (crossover) 和变异 (mutation)现象,从任一初始种群 (PopuIation) 出发,通过随机选择、交叉和变异操作,产生一群更适合环境的个体,使群体进化到搜索空间中越来越好的区域,这样一代一代不断繁衍进化,最后收敛到一群最适应环境的个体(lndividual) ,从而求得问题的优质解。

1.1 编码与解码

实现遗传算法的第一步就是明确对求解问题的编码和解码方式。所谓编码就是把要传递的信息按照一定的规则进行组织,所谓解码就是把收到的信息按照一定的规则进行解忻,且这个规则必须是编码者和解码者事先都知道或约定好的。

对于函数优化问题,一般有两种编码方式,各具优缺点

  • 实数编码:直接用实数表示基因,容易理解且不需要解码过程、但容易过早收敛,从而陷入局部最优
  • 二进制编码:稳定性高,种群多样性大,需要的存储空间大,需要解码且难以理解。

1.2 选择算子-轮盘赌法

在这里插入图片描述
轮盘赌选择法是依据个体的适应度值计算每个个体在子代中出现的概率,并按照此概率随机选择个体构成子代种群,因此该方法也被称为适应度比例法。轮盘赌选择策略的出发点是适应度值越好的个体被选择的概率越大。因此,在求解最大化问题的时候,我们可以直接采用适应度值来进行选择。但是在求解最小化问题的时候,我们必须首先将问题的适应度函数进行转换(如采用倒数或相反数)以将问题转化为最大化问题。

1.3 交叉算子

交叉操作是指从种群中随机选择两个个体,通过两个染色体的交换组合,把父串的优秀特征遗传给子串,从而产生新的优秀个体。体现了信息交换的思想。在实际应用中,使用率最高的是单点交叉算子,该算子在配对的染色体中随机的选择一个交叉位置,然后在该交叉位置对配对的染色体进行基因位变。其他交叉算子包括:双点交叉或多点交叉,均匀交叉,算术交叉。

1.4 变异算子

对种群中的每一个个体,以变异概率改变一个或多个基因座上的基因值为其他的等位基因。同生物界中一样,变异发生的概率很低,变异为新个体的产生了机会。

变异率一般可取0.001~0.1。变异率不能取得太大,如果大于0.5,遗传算法就会退化为随机搜索。

1.5 遗传算法流程

  • 对于一个实际问题,首先通过编码将解空间的数据表示为基因型串结构
  • 然后进行种群初始化,随机产生N个初始串结构数据,每个串结构数据称为一个个体,N个个体构成了一个群体。
  • 适应度表明个体或解的优劣性。
  • 选择的原则是适应性强的个体,为下一代贡献一个或多个后代的概率大。
  • 交叉操作可以得到新一代个体,新个体组合体现了其父辈个体的特性。
  • 变异过程以一定的概率随机地改变串结构数据中某个串的值。
  • 新种群满足条件时,停止进化。

1.6 基于遗传算法的栅格法机器人路径规划

机器人控制过程中,路径规划是其中重要的一环。因此本文采用遗传算法对机器人移动时的路径进行优化,最终选取出一条最优路径。采用栅格图法为机器人移动的地图进行建模,并根据遗传算法机理,在MATLAB上仿真实现了最优路径的选取。

首先对其进行编码,用0~24表示每个方格,如图所示路径编码为(0,1,7,13,19,24)。

种群初始化

  • 每行选择一个栅格
  • 判断相邻栅格是否连续
  • 不连续时进行插入栅格操作,直到连续

选择:如图所示有①②两条路径,对应两个个体。选择路径长度和路径平滑性作为评价指标:

交叉:如上图所示有①②两条路径,对应两个个体。通过交换交叉点前后的路径可形成新的路径。

变异:随机选择路径中的两个栅格。 采用种群初始化中的方法在两个栅格间产生新路径。

main

% 基于遗传算法的栅格法机器人路径规划
clc;
clear;
% 输入数据,即栅格地图
G=  [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0;0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0;0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0;0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0;0 0 0 0 0 0 1 1 1 0 1 0 1 1 0 0 0 0 0 0;0 1 1 1 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0;0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;0 0 0 0 0 0 0 1 1 0 1 1 1 1 0 0 0 0 0 0;0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0;0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 1 1 1 0;0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0;0 0 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0;0 0 1 1 0 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0;0 0 0 0 0 0 1 1 1 0 1 0 0 0 0 0 0 1 1 0; 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0;0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0;0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
%G = [0 0 0 1 0;
%     0 0 0 0 0;
%     0 0 1 0 0;
%     1 0 1 0 0;
%     0 0 0 0 0;];p_start = 0;   % 起始序号
p_end = 399;   % 终止序号
NP = 200;      % 种群数量
max_gen = 50;  % 最大进化代数
pc = 0.8;      % 交叉概率
pm = 0.2;      % 变异概率
%init_path = [];
z = 1;  
new_pop1 = {}; % 元包类型路径
[y, x] = size(G);
% 起点所在列(从左到右编号1.2.3...)
xs = mod(p_start, x) + 1; 
% 起点所在行(从上到下编号行1.2.3...)
ys = fix(p_start / x) + 1;
% 终点所在列、行
xe = mod(p_end, x) + 1;
ye = fix(p_end / x) + 1;% 种群初始化step1,必经节点,从起始点所在行开始往上,在每行中挑选一个自由栅格,构成必经节点
pass_num = ye - ys + 1;
pop = zeros(NP, pass_num);
for i = 1 : NPpop(i, 1) = p_start;j = 1;% 除去起点和终点for yk = ys+1 : ye-1j = j + 1;% 每一行的可行点can = []; for xk = 1 : x% 栅格序号no = (xk - 1) + (yk - 1) * x;if G(yk, xk) == 0% 把点加入can矩阵中can = [can no];endendcan_num = length(can);% 产生随机整数index = randi(can_num);% 为每一行加一个可行点pop(i, j) = can(index);endpop(i, end) = p_end;%pop% 种群初始化step2将上述必经节点联结成无间断路径single_new_pop = generate_continuous_path(pop(i, :), G, x);%init_path = [init_path, single_new_pop];if ~isempty(single_new_pop)new_pop1(z, 1) = {single_new_pop};z = z + 1;end
endmean_path_value = zeros(1, max_gen);
min_path_value = zeros(1, max_gen);
% 循环迭代操作
for i = 1 : max_gen% 计算适应度值% 计算路径长度path_value = cal_path_value(new_pop1, x)% 计算路径平滑度path_smooth = cal_path_smooth(new_pop1, x)fit_value = 1 .* path_value .^ -1 + 1 .* path_smooth .^ -1;mean_path_value(1, i) = mean(path_value);[~, m] = max(fit_value);min_path_value(1, i) = path_value(1, m);% 选择操作new_pop2 = selection(new_pop1, fit_value);% 交叉操作new_pop2 = crossover(new_pop2, pc);% 变异操作new_pop2 = mutation(new_pop2, pm, G, x);% 更新种群new_pop1 = new_pop2;end
% 画每次迭代平均路径长度和最优路径长度图
figure(1)
plot(1:max_gen,  mean_path_value, 'r')
hold on;
plot(1:max_gen, min_path_value, 'b')
legend('平均路径长度', '最优路径长度');
min_path_value(1, end)
% 在地图上画路径
[~, min_index] = max(fit_value);
min_path = new_pop1{min_index, 1};
figure(2)
hold on;
title('遗传算法机器人运动轨迹'); 
xlabel('坐标x'); 
ylabel('坐标y');
DrawMap(G);
[~, min_path_num] = size(min_path);
for i = 1:min_path_num% 路径点所在列(从左到右编号1.2.3...)x_min_path(1, i) = mod(min_path(1, i), x) + 1; % 路径点所在行(从上到下编号行1.2.3...)y_min_path(1, i) = fix(min_path(1, i) / x) + 1;
end
hold on;
plot(x_min_path, y_min_path, 'r')

selection

% 用轮盘赌法选择新的个体
% 输入变量:pop元胞种群,fitvalue:适应度值
% 输出变量:newpop选择以后的元胞种群
function [new_pop] = selection(pop, fit_value)
%构造轮盘
[px, ~] = size(pop);
total_fit = sum(fit_value);
p_fit_value = fit_value / total_fit;
p_fit_value = cumsum(p_fit_value);    % 概率求和
% 随机数从小到大排列
ms = sort(rand(px, 1));
fitin = 1;
newin = 1;
while newin <= pxif(ms(newin)) < p_fit_value(fitin)new_pop{newin, 1} = pop{fitin, 1};newin = newin+1;elsefitin = fitin+1;end
end

mutation

% 变异操作
% 函数说明
% 输入变量:pop:种群,pm:变异概率
% 输出变量:newpop变异以后的种群
function [new_pop] = mutation(pop, pm, G, x)
[px, ~] = size(pop);
new_pop = {};
for i = 1:px% 初始化最大迭代次数max_iteration = 0;single_new_pop = pop{i, 1};[~, m] = size(single_new_pop);% single_new_pop_slice初始化single_new_pop_slice = [];if(rand < pm)while isempty(single_new_pop_slice)% 生成2-(m-1)的两个随机数,并排序mpoint = sort(round(rand(1,2)*(m-3)) + [2 2]);single_new_pop_slice = [single_new_pop(mpoint(1, 1)-1) single_new_pop(mpoint(1, 2)+1)];single_new_pop_slice = generate_continuous_path(single_new_pop_slice, G, x);%max_iteration = max_iteration + 1;if max_iteration >= 100000breakendendif max_iteration >= 100000new_pop{i, 1} = pop{i, 1};elsenew_pop{i, 1} = [single_new_pop(1, 1:mpoint(1, 1)-1), single_new_pop_slice(2:end-1), single_new_pop(1, mpoint(1, 2)+1:m)];end% single_new_pop_slice再次初始化single_new_pop_slice = [];elsenew_pop{i, 1} = pop{i, 1};end
end

generate_continuous_path

% 将必经节点联结成无间断路径
function [single_new_pop] = generate_continuous_path(single_pop, G, x)
i = 1;
single_new_pop = single_pop;
[~, single_path_num] = size(single_new_pop);
while i ~= single_path_num% 点i所在列(从左到右编号1.2.3...)x_now = mod(single_new_pop(1, i), x) + 1; % 点i所在行(从上到下编号行1.2.3...)y_now = fix(single_new_pop(1, i) / x) + 1;% 点i+1所在列、行x_next = mod(single_new_pop(1, i + 1), x) + 1;y_next = fix(single_new_pop(1, i + 1) / x) + 1;% 初始化最大迭代次数max_iteration = 0;% 判断点i和i+1是否连续,若不连续插入值while max(abs(x_next - x_now), abs(y_next - y_now)) > 1x_insert = floor((x_next + x_now) / 2);y_insert = floor((y_next + y_now) / 2);% 插入栅格为自由栅格if G(y_insert, x_insert) == 0  % 栅格序号num_insert = (x_insert - 1) + (y_insert - 1) * x;% 插入新序号single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];% 插入栅格为障碍物栅格else   % 往左走if G(y_insert, x_insert - 1) == 0 && ((x_insert - 2) + (y_insert - 1) * x ~= single_new_pop(1, i)) && ((x_insert - 2) + (y_insert - 1) * x ~= single_new_pop(1, i+1))x_insert = x_insert - 1;% 栅格序号num_insert = (x_insert - 1) + (y_insert - 1) * x;% 插入新序号single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];% 往右走    elseif G(y_insert, x_insert + 1) == 0 && (x_insert + (y_insert - 1) * x ~= single_new_pop(1, i)) && (x_insert + (y_insert - 1) * x ~= single_new_pop(1, i+1))x_insert = x_insert + 1;% 栅格序号num_insert = (x_insert - 1) + (y_insert - 1) * x;% 插入新序号single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];% 向上走elseif G(y_insert + 1, x_insert) == 0 && ((x_insert - 1) + y_insert * x ~= single_new_pop(1, i)) && ((x_insert - 1) + y_insert * x ~= single_new_pop(1, i+1))y_insert = y_insert + 1;% 栅格序号num_insert = (x_insert - 1) + (y_insert - 1) * x;% 插入新序号single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];% 向下走elseif  G(y_insert - 1, x_insert) == 0 && ((x_insert - 1) + (y_insert - 2) * x ~= single_new_pop(1, i)) && ((x_insert - 1) + (y_insert-2) * x ~= single_new_pop(1, i+1))y_insert = y_insert - 1;% 栅格序号num_insert = (x_insert - 1) + (y_insert - 1) * x;% 插入新序号single_new_pop = [single_new_pop(1, 1:i), num_insert, single_new_pop(1, i+1:end)];% 其他情况舍去此路径else%break_pop = single_new_popsingle_new_pop = [];breakend    endx_next = x_insert;y_next = y_insert;max_iteration = max_iteration + 1;if max_iteration > 20000single_new_pop = [];breakendendif isempty(single_new_pop)breakend[~, single_path_num] = size(single_new_pop);i = i + 1;
end

DrawMap

%创建具有障碍物的栅格地图
%矩阵中1代表黑色栅格function G = DrawMap(G)
b = G;
b(end+1,end+1) = 0;
colormap([1 1 1;0 0 0]);  % 创建颜色
pcolor(0.5:size(G,2) + 0.5, 0.5:size(G,1) + 0.5, b); % 赋予栅格颜色
set(gca, 'XTick', 1:size(G,1), 'YTick', 1:size(G,2));  % 设置坐标
axis image xy;  % 沿每个坐标轴使用相同的数据单位,保持一致

crossover

%交叉变换
%输入变量:pop:父代种群,pc:交叉的概率
%输出变量:newpop:交叉后的种群
function [new_pop] = crossover(pop, pc)
[px,~] = size(pop);
% 判断路径点数是奇数或偶数
parity = mod(px, 2);
new_pop = {};
for i = 1:2:px-1singal_now_pop = pop{i, 1};singal_next_pop = pop{i+1, 1};[lia, lib] = ismember(singal_now_pop, singal_next_pop);[~, n] = find(lia == 1);[~, m] = size(n);if (rand < pc) && (m >= 3)% 生成一个2-m-1之间的随机数r = round(rand(1,1)*(m-3)) +2;crossover_index1 = n(1, r);crossover_index2 = lib(crossover_index1);new_pop{i, 1} = [singal_now_pop(1:crossover_index1), singal_next_pop(crossover_index2+1:end)];new_pop{i+1, 1} = [singal_next_pop(1:crossover_index2), singal_now_pop(crossover_index1+1:end)];elsenew_pop{i, 1} =singal_now_pop;new_pop{i+1, 1} = singal_next_pop;end
if parity == 1new_pop{px, 1} = pop{px, 1};
end
end

cal_path_value

% 计算路径长度函数
function [path_value] = cal_path_value(pop, x)
[n, ~] = size(pop);
path_value = zeros(1, n);
for i = 1 : nsingle_pop = pop{i, 1};[~, m] = size(single_pop);for j = 1 : m - 1% 点i所在列(从左到右编号1.2.3...)x_now = mod(single_pop(1, j), x) + 1; % 点i所在行(从上到下编号行1.2.3...)y_now = fix(single_pop(1, j) / x) + 1;% 点i+1所在列、行x_next = mod(single_pop(1, j + 1), x) + 1;y_next = fix(single_pop(1, j + 1) / x) + 1;if abs(x_now - x_next) + abs(y_now - y_next) == 1path_value(1, i) = path_value(1, i) + 1;elsepath_value(1, i) = path_value(1, i) + sqrt(2);endend
end

cal_path_smooth

% 计算路径平滑度函数
function [path_smooth] = cal_path_smooth(pop, x)
[n, ~] = size(pop);
path_smooth = zeros(1, n);
for i = 1 : nsingle_pop = pop{i, 1};[~, m] = size(single_pop);for j = 1 : m - 2% 点i所在列(从左到右编号1.2.3...)x_now = mod(single_pop(1, j), x) + 1; % 点i所在行(从上到下编号行1.2.3...)y_now = fix(single_pop(1, j) / x) + 1;% 点i+1所在列、行x_next1 = mod(single_pop(1, j + 1), x) + 1;y_next1 = fix(single_pop(1, j + 1) / x) + 1;% 点i+2所在列、行x_next2 = mod(single_pop(1, j + 2), x) + 1;y_next2 = fix(single_pop(1, j + 2) / x) + 1;% cos A=(b?+c?-a?)/2bcb2 = (x_now - x_next1)^2 + (y_now - y_next1)^2;c2 = (x_next2 - x_next1)^2 + (y_next2 - y_next1)^2;a2 = (x_now - x_next2)^2 + (y_now - y_next2)^2;cosa = (c2 + b2 - a2) / (2 * sqrt(b2) *  sqrt(c2));angle = acosd(cosa);if angle < 170 && angle > 91path_smooth(1, i) = path_smooth(1, i) + 3;elseif angle <= 91 && angle > 46path_smooth(1, i) = path_smooth(1, i) + 15;elseif angle <= 46path_smooth(1, i) = path_smooth(1, i) + 20;endend
end

运行效果:
在这里插入图片描述

二、采用模拟退火算法改善适应度函数

为了提高遗传算法运行效率和求解质量,这里引入模拟退火算法的思想,模拟退火(Stimulated Annealing, SA)具有较强的局部寻优能力,并能使搜索过程避免陷入局部最优解,采用模拟退火遗传算法(Stimulated Annealing Genetic Algorithm,SAGA)求解路径优化问题。

模拟退火遗传算法是对适应度函数的改进,在前期(高温)减少个体间的适应度差异,后期(低温)放大个体间适应度差异,突出优秀个体,完成适应度拉伸的作用,在一定程度上弥补了遗传算法在前期容易早熟、后期容易停滞的缺点。
具体的适应度值计算公式如下所示:

其中, M M M为种群大小, f i f_i fi为第𝑖个个体的适应度, g g g为遗传代数, T T T为温度, T 0 T_0 T0为初始温度, A A A为退火速度(本文取 T 0 = 100 , A = 0.8 T_0 = 100, A = 0.8 T0=100,A=0.8

SAGA_main

%%%%%%模拟退火遗传算法(SAGA)%%%%%%%%%%%
clc;
clear;
%%%设置超参数
p_crs = 0.7;   %交叉概率
p_mut = 0.1;   %变异概率
ratio = 0.5;   %选择操作中父辈的比例
pop_num = 5000;  %种群规模
chrom_len = 7;  %染色体长度,这里代表路线的点数
iteration = 40;
T0 = 100;  %初始温度
A = 0.8;  %退火速度% 一个个体就是一条路线
[x,y]=popinit(pop_num,chrom_len);   %产生初始种群   
fit=saga_fitness(x,y, T0);      %计算种群适应度
[bestx0,besty0,fit0]=best(x,y,fit); 
d0 = 0; %初始路径长度
for j=1:1:size(bestx0,2)-1d0 = d0 + sqrt((bestx0(1,j+1)-bestx0(1,j)).^2 + ...(besty0(1,j+1)-besty0(1,j)).^2);     %该个体(即路线)的路径长度
endfor i=1:1:iteration           %设置进化代数[Parentx,Parenty]=select(x, y, fit, ratio);      %选择[Kidx,Kidy]=crossover(Parentx,Parenty,p_crs);       %交叉[Kidx,Kidy]=mutation(Kidx,Kidy,p_mut);              %变异x = [Parentx; Kidx];    % 得到新的种群y = [Parentx; Kidy];x(:,chrom_len)=1.5;   % 保留终点y(:,chrom_len)=8.9;T = T0 * A^(i-1);  % 当前温度fit = saga_fitness(x,y,T);   % 计算进化后的适应度[bestx,besty,bestfit]=best(x,y,fit);   %选择每一代中的最佳个体route_x(i,:)=bestx;                     %保存该最佳个体route_y(i,:)=besty;route_fit(i)=bestfit;for j=1:1:size(bestx,2)-1dd(j)=sqrt((bestx(1,j+1)-bestx(1,j)).^2 + ...(besty(1,j+1)-besty(1,j)).^2);     %该个体(即路线)的路径长度endd(i) = sum(dd);   %有问题fprintf('%dth 代进化完成...\n', i)
%     plot(bestx,besty,'r-');
end
route_fit = [fit0, route_fit];   %加上初始种群中最优个体
route_x = [bestx0; route_x];
route_y = [bestx0; route_y];
d = [d0, d];[final_fit,idx]=max(route_fit);            %所有代中的的最佳路线
final_routex=route_x(idx,:);
final_routey=route_y(idx,:);
final_distance = min(d)             %最佳路径长度%==========画图,可视化路线、进化过程==============
% start point
xs=0;
ys=0;
% Destination
xt=1.5;
yt=8.9;
%obstacle
xobs=[1.5 4.0 1.2];
yobs=[6.5 3.0 1.5];
robs=[1.5 1.0 0.8];
theta=linspace(0,2*pi,100);
max_area = 0;
for k=1:numel(xobs)fill(xobs(k)+robs(k)*cos(theta),yobs(k)+robs(k)*sin(theta),[0.5 0.7 0.8]);  % 后一个参数表示RGB值text(xobs(k), yobs(k), num2str(k))hold on;
end
plot(xs,ys,'bs','MarkerSize',12,'MarkerFaceColor','y');
plot(xt,yt,'kp','MarkerSize',16,'MarkerFaceColor','g');
grid on;
hold on;%%画出最短路径的路线
plot(final_routex,final_routey,'r*-',  'linewidth', 1.5);
legend('障碍物1','障碍物2','障碍物3','起点', '终点', '最短路线')
set(gca,'FontSize',16);
hold off;% 进化过程中适应度曲线
figure,
% plot(0:1:size(route_fit,2)-1, route_fit, 'linewidth', 1.2)
plot(d, 'linewidth', 1.2)
% ylim([0.08,0.1])
title(['变异率=',num2str(p_mut),',交叉率=', num2str(p_crs), '的进化曲线']);
legend('最短路径长度值', 'Location', 'northeast');
set(gca,'FontSize',16);d_saga = d;
save('d_saga');load('d_ga.mat');
figure,
plot(d, 'linewidth', 1.2), hold on,
plot(d_ga, 'linewidth', 1.2);
title(['变异率=',num2str(p_mut),',交叉率=', num2str(p_crs), '的进化曲线']);
legend('SAGA最优路径值', 'GA最优路径值', 'Location', 'northeast');
set(gca,'FontSize',16);

select

%====================================
%%输入参数:种群、其适应度、选择比例
%%输出参数:父辈种群——x,y横纵坐标
%%说明:
%     按照输入参数的比例,从种群中选择父代
%====================================
function [parentPopx, parentPopy]=select(popx, popy, fitness, ratio)totalfit=sum(fitness); %适应值之和accP=cumsum(fitness/totalfit); %概率累计和%轮盘赌选择算法for n=1:round(ratio*size(popx,1))mat=find(accP>rand); %找到比随机数大的累积概率if isempty(mat)continueendparentPopx(n,:)=popx(mat(1),:);%将首个比随机数大的累积概率的位置的个体遗传下去parentPopy(n,:)=popy(mat(1),:);end
end

saga_fitness

%====================================
%%输入参数:种群——x,y横纵坐标, 当前温度T
%%输出参数:种群中每个个体的适应度值
%%说明:
%     逐个计算种群中个体的适应度值,判断该个体所连成线路与圆形障碍物之间的关系,
%     将满足条件的路径的距离倒数作为适应度值
%====================================function fitval=saga_fitness(x,y,T)%obstaclexobs=[1.5 4.0 1.2];yobs=[6.5 3.0 1.5];robs=[1.5 1.0 0.8];[n, xn] = size(x);for i=1:1:ncnt_line = 0;  %记录穿过障碍物的线段数%%拆分相邻的两个点,便于后续计算for m=1:1:xn-1x1(m)=x(i,m);y1(m)=y(i,m);endfor n=2:1:xnx2(n-1)=x(i,n);y2(n-1)=y(i,n);end%%判断线段与障碍物的关系for m = 1:size(x1,2)A = y2(m) - y1(m);B = x1(m) - x2(m);C = y1(m)*(x2(m)-x1(m)) - x1(m)*(y2(m)-y1(m));for ii = 1:3if ((x1(m)-xobs(ii))^2 + (y1(m)-yobs(ii))^2) < robs(ii)^2 || ((x2(m)-xobs(ii))^2 + (y2(m)-yobs(ii))^2) < robs(ii)^2% disp('有点在圆内')cnt_line = cnt_line + 1;continue;else            d = abs(A*xobs(ii)+B*yobs(ii)+C) / sqrt(A^2+B^2);if d==0d1 = (xobs(ii)-x1(m))^2 + (yobs(ii)-y1(m))^2;d2 = (x2(m)-x1(m))^2 + (y2(m)-y1(m))^2;if d1 < d2cnt_line = cnt_line + 1;   % 该线段过圆心且穿过圆endelseif d < robs(ii)cos1 = (x2(m)-x1(m))*(xobs(ii)-x1(m)) + (y2(m)-y1(m))*(yobs(ii)-y1(m));cos2 = (x1(m)-x2(m))*(xobs(ii)-x2(m)) + (y1(m)-y2(m))*(yobs(ii)-y2(m));if cos1>0 && cos2>0cnt_line = cnt_line + 1;    % 该线段与圆交与两点endelsecontinue;endendendend%%%计算适应度if cnt_line > 0f(i)=0;       %路线穿过障碍物的个体适应度置零elsefor j=1:1:xn-1d(j)=sqrt((x(i,j+1)-x(i,j)).^2+(y(i,j+1)-y(i,j)).^2);     %该个体(即路线)的路径长度endf(i)=1.0/sum(d);       %取距离的倒数作为个体适应度endrecord_cnt(i,:) = cnt_line;endI = find(f ~= 0);sumf = sum(exp(f(I) ./ T)) + n - size(I, 1);f(I) = exp(f(I)./T) ./ sumf;fitval=f';
%     disp(['不满足条件的最小线段数为:',num2str(min(record_cnt, [], 1))])end

popinit

%====================================
%%输入参数:种群数量,染色体长度
%%输出参数:初始种群
%%说明:
%     种群中的个体由一系列点组成,该点的x,y坐标分开存放,
%     除了起点和终点,其余点随机生成并从小到大排序
%====================================
function [x,y]=popinit(popsize,chromlength)x=5.0*rand(popsize,chromlength);y=8.9*rand(popsize,chromlength);x(:,1)=0;  % 设置起点y(:,1)=0;for i=1:1:size(x,1) x(i,:)=sort(x(i,:));y(i,:)=sort(y(i,:));end x(:,chromlength)=1.5;  %设置终点y(:,chromlength)=8.9;end

mutation

%====================================
%%输入参数:父代种群,变异概率
%%输出参数:子代种群
%%说明:
%     随机替换,最后需要从小到大排序
%====================================
function [kidx, kidy]=mutation(x, y, p)[m, n] = size(x);kidx = x;kidy = y;for i = 1:1:mif(rand < p)point = round(rand*n);% 避免越界if point <= 1point = 2;endif point == npoint = n-1;end% 变异:随机数替换kidx(i,point) = round(rand*n);kidy(i,point) = round(rand*n);endendfor i = 1:1:mkidx(i,:) = sort(kidx(i,:));kidy(i,:) = sort(kidy(i,:));end 
end

fitness

%====================================
%%输入参数:种群——x,y横纵坐标
%%输出参数:种群中每个个体的适应度值
%%说明:
%     逐个计算种群中个体的适应度值,判断该个体所连成线路与圆形障碍物之间的关系,
%     将满足条件的路径的距离倒数作为适应度值
%====================================function fitval=fitness(x,y)%obstaclexobs=[1.5 4.0 1.2];yobs=[6.5 3.0 1.5];robs=[1.5 1.0 0.8];[n, xn] = size(x);for i=1:1:ncnt_line = 0;  %记录穿过障碍物的线段数%%拆分相邻的两个点,便于后续计算for m=1:1:xn-1x1(m)=x(i,m);y1(m)=y(i,m);endfor n=2:1:xnx2(n-1)=x(i,n);y2(n-1)=y(i,n);end%%判断线段与障碍物的关系for m = 1:size(x1,2)A = y2(m) - y1(m);B = x1(m) - x2(m);C = y1(m)*(x2(m)-x1(m)) - x1(m)*(y2(m)-y1(m));for ii = 1:3if ((x1(m)-xobs(ii))^2 + (y1(m)-yobs(ii))^2) < robs(ii)^2 || ((x2(m)-xobs(ii))^2 + (y2(m)-yobs(ii))^2) < robs(ii)^2% disp('有点在圆内')cnt_line = cnt_line + 1;continue;else            d = abs(A*xobs(ii)+B*yobs(ii)+C) / sqrt(A^2+B^2);if d==0d1 = (xobs(ii)-x1(m))^2 + (yobs(ii)-y1(m))^2;d2 = (x2(m)-x1(m))^2 + (y2(m)-y1(m))^2;if d1 < d2cnt_line = cnt_line + 1;   % 该线段过圆心且穿过圆endelseif d < robs(ii)cos1 = (x2(m)-x1(m))*(xobs(ii)-x1(m)) + (y2(m)-y1(m))*(yobs(ii)-y1(m));cos2 = (x1(m)-x2(m))*(xobs(ii)-x2(m)) + (y1(m)-y2(m))*(yobs(ii)-y2(m));if cos1>0 && cos2>0cnt_line = cnt_line + 1;    % 该线段与圆交与两点endelsecontinue;endendendend%%%计算适应度if cnt_line > 0f(i)=0;       %路线穿过障碍物的个体适应度置零elsefor j=1:1:xn-1d(j)=sqrt((x(i,j+1)-x(i,j)).^2+(y(i,j+1)-y(i,j)).^2);     %该个体(即路线)的路径长度endf(i)=1.0/sum(d);       %取距离的倒数作为个体适应度endrecord_cnt(i,:) = cnt_line;endfitval=f';
%     disp(['不满足条件的最小线段数为:',num2str(min(record_cnt, [], 1))])end

crossover

%====================================
%%输入参数:父代种群,交叉概率
%%输出参数:子代种群
%%说明:
%     单点交叉,最后需要从小到大排序
%====================================
function [kidx, kidy]=crossover(x, y, p)[m,n] = size(x);kidx = ones(size(x)); kidy = ones(size(y)); for i = 1:2:m-1if(rand < p)point = round(rand*n);kidx(i,:) = [x(i,1:point),x(i+1,point+1:n)];kidx(i+1,:) = [x(i+1,1:point),x(i,point+1:n)];kidy(i,:) = [y(i,1:point),y(i+1,point+1:n)];kidy(i+1,:) = [y(i+1,1:point),y(i,point+1:n)];elsekidx(i,:) = x(i,:);kidx(i+1,:) = x(i+1,:);kidy(i,:) = y(i,:);kidy(i+1,:) = y(i+1,:);endendfor i = 1:1:mkidx(i,:) = sort(kidx(i,:));kidy(i,:) = sort(kidy(i,:));end 
end

best

%====================================
%%输入参数:种群、其适应度
%%输出参数:种群中的最佳个体,及其适应度
%%说明:
%     选择最佳个体,便于后续分析
%====================================
function [bestx,besty,bestfit]=best(x,y,fitval)bestx = x(1,:);besty = y(1,:);bestfit = fitval(1);for i = 2:size(x,1)if fitval(i) > bestfitbestx = x(i,:);besty = y(i,:);bestfit=fitval(i);endend
end

运行效果
在这里插入图片描述

参考:
[1]https://www.bilibili.com/video/BV1XC4y1J7cN/?spm_id_from=333.337.search-card.all.click&vd_source=7a4fcf1e79c6c978598c4f5c8e5dddf0
[2]https://zhuanlan.zhihu.com/p/100337680
[3]https://zhuanlan.zhihu.com/p/136393730
[4]https://blog.csdn.net/weixin_44231148/article/details/112918109?spm=1001.2014.3001.5506
[5]https://blog.csdn.net/hba646333407/article/details/103251008
[6]https://blog.csdn.net/u011125673/article/details/97398874
[7]http://t.csdnimg.cn/nQsrf
[8]https://blog.csdn.net/KeepingMatlab/article/details/134624717
[9]https://zhuanlan.zhihu.com/p/266874840

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/282395.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

王道考研--》单链表课后习题C语言代码实现(冲刺)

考研是许多计算机科学专业学生追求高学历、寻求更好就业前景的途径。在考研过程中&#xff0c;数据结构是一个非常重要的科目&#xff0c;而代码实现题更是其中的难点之一。在这篇文章中&#xff0c;我们将探讨如何通过实现数据结构代码问题来提升考研成绩。无论您是否有编程经…

Linux:TCP 序列号简介

文章目录 1. 前言2. 什么是 TCP 序列号&#xff1f;3. TCP 序号 的 初始值设置 和 后续变化过程3.1 三次握手 连接建立 期间 客户端 和 服务端 序号 的 变化过程3.1.1 客户端 socket 初始序号 的 建立3.1.2 服务端 socket 初始序号 的 建立3.1.3 客户端 socket 接收 服务端 SAC…

2024年最免费的DAW混音编曲FL Studio21.2.中文版下载

FL Studio 简称FL&#xff0c;全称Fruity Loops Studio&#xff0c;因此国人习惯叫它"水果"。目前最新版本是FL Studio21.1.1.3750版本&#xff0c;它让你的计算机就像是全功能的录音室&#xff0c;大混音盘&#xff0c;非常先进的制作工具&#xff0c;让你的音乐突破…

欧睿 × 和鲸:联合打造 AI 中台赋能企业数字化转型,大幅提升模型产品研发效率

近年来&#xff0c;在泛零售及快消行业&#xff0c;由于市场格局越发瞬息万变、消费场景愈加错综复杂&#xff0c;以机器学习算法、人工智能模型代替纯人脑人工完成商品计划、运营、供应链管理已逐渐成为主流。 oIBP 欧睿数据&#xff08;下简称“欧睿”&#xff09;是国内领先…

【C++】模板

这篇博客来说一下模板&#xff0c;模板有函数模板和类模板&#xff0c;先来看函数模板&#xff0c;你一听模板这个词就是提前给好一个模具&#xff0c;等我们用的时候在去套用 比如说&#xff1a;我们在实际应用中常常用到swap这个交换函数&#xff0c;但是呢&#xff0c;我们要…

phpMyAdmin的常见安装位置

nginx的日志显示有人一直在尝试访问phpMyAdmin的setup.php&#xff0c;用了各种位置。 其实我只有一个nginx&#xff0c;别的什么也没有。 47.99.136.156 - - [01:44:37 0800] "GET http://abc.com:80/phpMyAdmin/scripts/setup.php HTTP/1.0" 404 162 "-"…

VUE中的8种常规通信方式

文章目录 1.props传递数据(父向子)2.$emit触发自定义事件&#xff08;子向父&#xff09;3.ref&#xff08;父子&#xff09;4.EventBus&#xff08;兄弟组件&#xff09;5.parent或root&#xff08;兄弟组件&#xff0c;有共同祖辈&#xff09;6.attrs和listeners&#xff08;…

海安行车记录仪avi杀病毒导致文件丢失的恢复案例

海安行车记录仪&#xff0c;听名字就知道是个小小小品牌&#xff0c;而且用的文件格式是比较古老的AVI&#xff0c;这种文件格式是微软设计的&#xff0c;后来并没有普及&#xff08;不支持4G以上大文件而且结构过于松散&#xff09;。这个恢复案例比较特殊的地方是不太清楚做过…

[NCTF2019]Fake XML cookbook1

提示 xml注入 一般遇到像登录页之类的就因该想到sql注入、弱口令或者xml等 随便输入抓包 这里明显就是xml注入 这里我们来简单了解一下xml注入 这里是普通的xml注入 xml注入其实和sql注入类似&#xff0c;利用了xml的解析机制如果系统没有将‘<’‘>’进行转义&#xff0…

Ubuntu18.04.6下samba服务的安装及配置

目录 01 安装samba服务&#xff1a; 03 重启samba服务 04 设置samba登录密码 05 测试 前言 从本章开始我们将要学习嵌入式音视频的学习了 &#xff0c;使用的瑞芯微的开发板 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博…

SearchWP WordPress高级网站内容搜索插件(包含所有专业扩展)

点击阅读SearchWP WordPress高级网站内容搜索插件(包含所有专业扩展)原文 SearchWP WordPress高级网站内容搜索插件是一个非常强大的工具&#xff0c;可以显着增强您网站的搜索功能。通过向网站访问者提供高度相关和精确的搜索结果&#xff0c;它可以有效地简化他们的搜索过程…

Leetcode的AC指南 —— 链表:24. 两两交换链表中的节点

摘要&#xff1a; Leetcode的AC指南 —— 链表&#xff1a;24. 两两交换链表中的节点。题目介绍&#xff1a;给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能…