遗传算法最全交叉函数的MATLAB代码

遗传算法中的交叉(crossover)函数是用来创建新的解决方案(即 offspring 或 children)的方法,以下是五种常见的交叉函数的 MATLAB 实现:

1. 单点交叉 (Single-Point Crossover)

在单点交叉中,我们随机选择一个切割点,然后交换两个父代染色体在切割点之后的部分。

function [child1, child2] = singlePointCrossover(parent1, parent2)

    crossover_point = randi([1 length(parent1)], 1, 1);

    child1 = [parent1(1:crossover_point) parent2(crossover_point+1:end)];

    child2 = [parent2(1:crossover_point) parent1(crossover_point+1:end)];

end

2. 两点交叉 (Two-Point Crossover)

在两点交叉中,我们随机选择两个切割点,然后交换两个父代染色体在这两个点之间的部分。

function [child1, child2] = twoPointCrossover(parent1, parent2)

    crossover_points = sort(randi([1 length(parent1)], 1, 2));

    child1 = [parent1(1:crossover_points(1)) parent2(crossover_points(1)+1:crossover_points(2)) parent1(crossover_points(2)+1:end)];

    child2 = [parent2(1:crossover_points(1)) parent1(crossover_points(1)+1:crossover_points(2)) parent2(crossover_points(2)+1:end)];

end

3. 均匀交叉 (Uniform Crossover)

在均匀交叉中,我们对每个位进行决策,随机决定该位来自于哪个父代染色体。

function [child1, child2] = uniformCrossover(parent1, parent2, crossoverRate)

    child1 = parent1;

    child2 = parent2;

    for i = 1:length(parent1)

        if rand < crossoverRate

            child1(i) = parent2(i);

            child2(i) = parent1(i);

        end

    end

end

4. 算术交叉 (Arithmetic Crossover)

在算术交叉中,我们根据一个随机权重对两个父代染色体进行线性组合。

function [child1, child2] = arithmeticCrossover(parent1, parent2)

    alpha = rand;

    child1 = alpha*parent1 + (1-alpha)*parent2;

    child2 = alpha*parent2 + (1-alpha)*parent1;

end

5. 部分匹配交叉 (Partially Matched Crossover, PMX)

部分匹配交叉主要用于排列问题,它保证了交叉后的染色体仍然是一个有效的排列。

function [child1, child2] = pmxCrossover(parent1, parent2)

    length_p = length(parent1);

    crossover_points = sort(randi([1 length_p], 1, 2));

    segment1 = parent1(crossover_points(1):crossover_points(2));

    segment2 = parent2(crossover_points(1):crossover_points(2));

    child1 = mapOrder(parent1, segment2, segment1, crossover_points);

    child2 = mapOrder(parent2, segment1, segment2, crossover_points);

end

function child = mapOrder(parent, segment1, segment2, crossover_points)

    child = parent;

    child(crossover_points(1):crossover_points(2)) = segment1;

    for i = [1:crossover_points(1)-1, crossover_points(2)+1:length(parent)]

        if ismember(child(i), segment1)

            index = find(segment2 == child(i));

            while ismember(segment1(index), child)

                index = find(segment2 == segment1(index));

            end

            child(i) = segment1(index);

        end

    end

end

6. 循环交叉 (Cycle Crossover, CX)

循环交叉是一种主要用于处理排列编码问题的交叉方法。它能够保持基因的绝对位置不变。

function [child1, child2] = cycleCrossover(parent1, parent2)

    length_p = length(parent1);

    cycleStart = 1;

    cycleIndex = cycleStart;

    child1 = zeros(1, length_p);

    child2 = zeros(1, length_p);

    while any(child1 == 0)

        child1(cycleIndex) = parent1(cycleIndex);

        child2(cycleIndex) = parent2(cycleIndex);

        cycleVal = parent2(cycleIndex);

        cycleIndex = find(parent1 == cycleVal);

        if parent1(cycleStart) == parent2(cycleIndex)

            cycleStart = find(child1 == 0, 1, 'first');

            cycleIndex = cycleStart;

        end

    end

end

7. 顺序交叉 (Order Crossover, OX)

顺序交叉也是一种主要用于处理排列编码问题的交叉方法。它能够保持基因的相对顺序不变。

function [child1, child2] = orderCrossover(parent1, parent2)

    length_p = length(parent1);

    crossover_points = sort(randi([1 length_p], 1, 2));

    segment1 = parent1(crossover_points(1):crossover_points(2));

    segment2 = parent2(crossover_points(1):crossover_points(2));

    child1 = fillOrder(parent1, segment2, crossover_points);

    child2 = fillOrder(parent2, segment1, crossover_points);

end

function child = fillOrder(parent, segment, crossover_points)

    child = zeros(1, length(parent));

    child(crossover_points(1):crossover_points(2)) = segment;

    j = 1;

    for i = 1:length(parent)

        if ~ismember(parent(i), child)

            while child(j) ~= 0

                j = j + 1;

            end

            child(j) = parent(i);

        end

    end

end

8. 位置交叉 (Position Based Crossover, POS)

位置交叉是另一种主要用于处理排列编码问题的交叉方法。它从一个父代继承一组基因的位置,从另一个父代继承这些位置上的基因。

function [child1, child2] = positionCrossover(parent1, parent2)

    length_p = length(parent1);

    positions = randi([0 1], 1, length_p);

    child1 = fillPosition(parent1, parent2, positions);

    child2 = fillPosition(parent2, parent1, positions);

end

function child = fillPosition(parent1, parent2, positions)

    child = zeros(1, length(parent1));

    child(positions == 1) = parent1(positions == 1);

    j = 1;

    for i = 1:length(parent1)

        if ~ismember(parent2(i), child)

            while child(j) ~= 0

                j = j + 1;

            end

            child(j) = parent2(i);

        end

    end

end

9. 模拟二进制交叉 (Simulated Binary Crossover, SBX)

模拟二进制交叉是一种用于处理实数编码问题的交叉方法。它通过模仿二进制编码的单点交叉来生成子代。

function [child1, child2] = simulatedBinaryCrossover(parent1, parent2, eta)

    length_p = length(parent1);

    child1 = zeros(1, length_p);

    child2 = zeros(1, length_p);

    for i = 1:length_p

        r = rand;

        if r <= 0.5

            beta = (2*r)^(1/(eta+1));

        else

            beta = (1/(2*(1-r)))^(1/(eta+1));

        end

        child1(i) = 0.5*(((1+beta)*parent1(i)) + (1-beta)*parent2(i));

        child2(i) = 0.5*(((1-beta)*parent1(i)) + (1+beta)*parent2(i));

    end

end

10. 模板交叉 (Template Crossover)

模板交叉使用一个模板来决定每个基因应该来自哪个父代。模板是一串和染色体一样长的二进制串。

function [child1, child2] = templateCrossover(parent1, parent2, template)

    child1 = parent1;

    child2 = parent2;

    child1(template == 1) = parent2(template == 1);

    child2(template == 1) = parent1(template == 1);

end

11. 最大最小交叉 (Max-min Arithmetic Recombination)

在最大最小交叉中,我们用两个父代染色体的最大值和最小值来创建子代染色体。

function [child1, child2] = maxminCrossover(parent1, parent2)

    child1 = max(parent1, parent2);

    child2 = min(parent1, parent2);

end

12. 混合交叉 (Blend Crossover, BLX-alpha)

混合交叉是一种用于实数编码问题的交叉方法。这种方法生成的子代在每个维度上都位于父代的中心附近。

function [child1, child2] = blendCrossover(parent1, parent2, alpha)

    child1 = (1 - alpha)*parent1 + alpha*parent2;

    child2 = alpha*parent1 + (1 - alpha)*parent2;

end

13. 中间交叉 (Intermediate Crossover)

中间交叉是一种用于实数编码问题的交叉方法。这种方法生成的子代在每个维度上都位于父代的中间。

function [child1, child2] = intermediateCrossover(parent1, parent2)

    child1 = 0.5*(parent1 + parent2);

    child2 = 0.5*(parent1 + parent2);

end

14. 线性组合交叉 (Linear Combination Crossover)

线性组合交叉是一种用于实数编码问题的交叉方法。这种方法根据随机权重对父代进行线性组合,生成子代。

function [child1, child2] = linearCombinationCrossover(parent1, parent2)

    alpha = rand;

    beta = rand;

    child1 = alpha*parent1 + (1 - alpha)*parent2;

    child2 = beta*parent1 + (1 - beta)*parent2;

end

15. 一致交叉 (Heuristic Crossover)

一致交叉是一种用于实数编码问题的交叉方法。这种方法考虑了父代的适应度,生成一个更好的子代。

function child = heuristicCrossover(parent1, parent2, fitness1, fitness2)

    if fitness1 > fitness2

        best = parent1;

        worst = parent2;

    else

        best = parent2;

        worst = parent1;

    end

    beta = rand;

    child = best + beta*(best - worst);

end

简单的遗传算法,计算函数最值. function ga_main() % 遗传算法程序 % n-- 种群规模% ger-- 迭代次数% pc--- 交叉概率% pm-- 变异概率 % v-- 初始种群(规模为n)% f-- 目标函数值% fit-- 适应度向量 % vx-- 最优适应度值向量% vmfit-- 平均适应度值向量 clear all; close all; clc;%清屏 tic;%计时器开始计时 n=20;ger=100;pc=0.65;pm=0.05;%初始化参数 %以上为经验值,可以更改。 % 生成初始种群 v=init_population(n,22); %得到初始种群,22串长,生成20*22的0-1矩阵 [N,L]=size(v); %得到初始规模行,列 disp(sprintf('Number of generations:%d',ger)); disp(sprintf('Population size:%d',N)); disp(sprintf('Crossover probability:%.3f',pc)); disp(sprintf('Mutation probability:%.3f',pm)); %sprintf可以控制输出格式 % 待优化问题 xmin=0;xmax=9; %变量X范围 f='x+10*sin(x.*5)+7*cos(x.*4)'; % 计算适应度,并画出初始种群图形 x=decode(v(:,1:22),xmin,xmax);"位二进制换成十进制,%冒号表示对所有行进行操作。 fit=eval(f);%eval转化成数值型的 %计算适应度 figure(1);%打开第一个窗口 fplot(f,[xmin,xmax]);%隐函数画图 grid on;hold on; plot(x,fit,'k*');%作图,画初始种群的适应度图像 title('(a)染色体的初始位置');%标题 xlabel('x');ylabel('f(x)');%标记轴 % 迭代前的初始化 vmfit=[];%平均适应度 vx=[]; %最优适应度 it=1; % 迭代计数器 % 开始进化 while it<=ger %迭代次数 0代 %Reproduction(Bi-classist Selection) vtemp=roulette(v,fit);%复制算子 %Crossover v=crossover(vtemp,pc);%交叉算子 %Mutation变异算子 M=rand(N,L)<=pm;%这里的作用找到比0.05小的分量 %M(1,:)=zeros(1,L); v=v-2.*(v.*M)+M;%两个0-1矩阵相乘后M是1的地方V就不变,再乘以2. NICE!!确实好!!!把M中为1的位置上的地方的值变反 %这里是点乘 %变异 %Results x=decode(v(:,1:22),xmin,xmax);%解码,求目标函数值 fit=eval(f); %计算数值 [sol,indb]=max(fit);% 每次迭代中最优目标函数值,包括位置 v(1,:)=v(indb,:); %用最大值代替 fit_mean=mean(fit); % 每次迭代中目标函数值的平均值。mean求均值 vx=[vx sol]; %最优适应度值 vmfit=[vmfit fit_mean];%适应度均值 it=it+1; %迭代次数计数器增加 end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MATLAB代码顾问

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值