【问题标题】:How to implement Roulette Wheel Selection and Rank Sleection on Matlab code for the Traveling Salesman Problom?如何在 Matlab 代码中针对旅行商问题实现轮盘赌选择和排名选择?
【发布时间】:2015-08-14 02:46:43
【问题描述】:

我有一个作业,为旅行商问题编码遗传算法。我已经使用锦标赛选择编写了一些给出正确结果的代码。 问题是,我必须做 Wheel 和 Rank,我得到的结果不正确。

这是我使用锦标赛选择的代码:

clc;
clear all;
close all;

nofCities = 30;
initialPopulationSize = nofCities*nofCities;
generations = nofCities*ceil(nofCities/10);

cities = floor(rand([nofCities 2])*100+1);

figure;
hold on;
scatter(cities(:,1), cities(:,2), 5, 'b','fill');
line(cities(:,1), cities(:,2));
line(cities([1 end],1), cities([1 end],2));
axis([0 110 0 110]);

population = zeros(initialPopulationSize ,nofCities);

for i=1:initialPopulationSize 
   population(i,:) = randperm(nofCities);
end

distanceMatrix = zeros(nofCities);
for i=1:nofCities
    for j=1:nofCities
        if (i==j)
            distanceMatrix(i,j)=0;
        else
            distanceMatrix(i,j) = sqrt((cities(i,1)-cities(j,1))^2+(cities(i,2)-cities(j,2))^2);
        end
    end
end

for u=1:generations     
    tourDistance = zeros(initialPopulationSize ,1);
    for i=1:initialPopulationSize 
       for j=1:length(cities)-1
           tourDistance(i) = tourDistance(i) + distanceMatrix(population(i,j),population(i,j+1));
       end
    end
    for i=1:initialPopulationSize 
        tourDistance(i) = tourDistance(i) + distanceMatrix(population(i,end),population(i,1));
    end

    min(tourDistance)

    newPopulation = zeros(initialPopulationSize,nofCities);

    for k=1:initialPopulationSize
        child = zeros(1,nofCities);
        %tournament start
        for i=1:5
           tournamentParent1(i) = ceil(rand()*initialPopulationSize);
        end
        p1 = find(tourDistance == min(tourDistance([tournamentParent1])));
        parent1 = population(p1(1), :);
        for i=1:5
           tournamentParent2(i) = ceil(rand()*initialPopulationSize);
        end
        p2 = find(tourDistance == min(tourDistance([tournamentParent2])));
        parent2 = population(p2(1), :);
        %tournament end
        %crossover
        startPos = ceil(rand()*(nofCities/2));
        endPos = ceil(rand()*(nofCities/2)+10);

        for i=1:nofCities
           if (i>startPos && i<endPos) 
               child(i) = parent1(i);
           end
        end

        for i=1:nofCities
            if (isempty(find(child==parent2(i))))
                for j=1:nofCities
                    if (child(j) == 0)
                        child(j) = parent2(i);
                        break;
                    end
                end
            end
        end

        newPopulation(k,:) = child;
    end

    %mutation
    mutationRate = 0.015;
    for i=1:initialPopulationSize
       if (rand() < mutationRate)
           pos1 = ceil(rand()*nofCities);
           pos2 = ceil(rand()*nofCities);
           mutation1 = newPopulation(i,pos1);
           mutation2 = newPopulation(i,pos2);
           newPopulation(i,pos1) = mutation2;
           newPopulation(i,pos2) = mutation1;           
       end
    end

    population = newPopulation;
    u
end

figure;
hold on;
scatter(cities(:,1), cities(:,2), 5, 'b','fill');
line(cities(population(i,:),1), cities(population(i,:),2));
line(cities([population(i,1) population(i,end)],1), cities([population(i,1) population(i,end)],2));
axis([0 110 0 110]);

%close all;

我想要的是用轮盘和排名代码替换锦标赛代码。

这是我为车轮选择写的:

 fitness = tourDistance./sum(tourDistance);
        wheel = cumsum(fitness);
        parent1 = population(find(wheel >= rand(),1),:);
        parent2 = population(find(wheel >= rand(),1),:);

【问题讨论】:

    标签: algorithm matlab genetic-algorithm roulette-wheel-selection


    【解决方案1】:

    这是一个在 Matlab 中进行轮盘选择的矢量化实现:

    [~,W] = min(ones(popSize,1)*rand(1,2*popSize) > ((cumsum(fitness)*ones(1,2*popSize)/sum(fitness))),[],1);
    

    这假设选择方案的适应度输入是一个大小为 (popSize x 1) 的矩阵(或与人口成员数量相同大小的列向量)。

    popSize 显然是您的人口中的成员数量。 W 是获胜者或被选为父母/交叉的种群成员。

    选择的输出将是 selected_pa​​rents ,它是大小为 2*popSize 的双行向量,其中包含将在交叉阶段使用的总体成员的所有索引。

    然后可以将此行向量输入到向量化交叉方案中,该方案可能如下所示:

    %% Single-Point Preservation Crossover
        Pop2 = Pop(W(1:2:end),:);                       % Pop2 Winners 1
        P2A  = Pop(W(2:2:end),:);                       % Pop2 Winners 2
        Lidx = sub2ind(size(Pop),[1:popSize]',round(rand(popSize,1)*(genome-1)+1));
        vLidx = P2A(Lidx)*ones(1,genome);
        [r,c]=find(Pop2==vLidx);
        [~,Ord]=sort(r);
        r = r(Ord); c = c(Ord);
        Lidx2 = sub2ind(size(Pop),r,c);
        Pop2(Lidx2) = Pop2(Lidx);
        Pop2(Lidx) = P2A(Lidx);
    

    此交叉假设输入来自选择方案的 W 变量。它还使用 Pop,它是按基因组矩阵存储在 popSize 中的种群成员。 (基因组是一次旅行中的城市数量,也恰好是基因组的大小)。基因组存储为一个整数数组,每个整数代表一个城市,行程定义为从基因组数组的值从数组的第一个索引到数组的最后一个索引的顺序。

    当我们这样做时,我们还可以为排列遗传算法(就是这样)包含一个很好的矢量化变异方案。

         %% Mutation (Permutation)
            idx = rand(popSize,1)<mutRate;
            Loc1 = sub2ind(size(Pop2),1:popSize,round(rand(1,popSize)*(genome-1)+1));
            Loc2 = sub2ind(size(Pop2),1:popSize,round(rand(1,popSize)*(genome-1)+1));
    
            Loc2(idx == 0) = Loc1(idx == 0);
            [Pop2(Loc1), Pop2(Loc2)] = deal(Pop2(Loc2), Pop2(Loc1));
    

    这种突变随机翻转了我们游览(基因组)中 2 个城市的顺序。

    最后确保在我们完成所有工作后更新您的人口!

    %% Update Population!
    Pop = Pop2; % updates the population to include crossovers and mutation.
    

    所以我知道这个回复对于你的任务来说可能为时已晚,但希望它能帮助遇到类似问题的其他人。

    我真的非常推荐任何对 Matlab 中的矢量化遗传算法感兴趣的人阅读这篇论文:UCL: Efficiently Vectorized Code for Population Based Optimization Algorithms

    这是我在示例中所有代码的基础,它会告诉你为什么要这样编写代码。它是一个很好的资源,也是我开始使用 GA 的原因。

    【讨论】:

      【解决方案2】:

      要使车轮选择发挥作用,您应该首先设计一个健身措施,让更健康的个体具有更大的价值。与距离更好的个体具有较小的值相反。那么你使用 cumsum 的方法应该会奏效。

      排名选择的问题在哪里?

      【讨论】:

        猜你喜欢
        • 2018-07-04
        • 1970-01-01
        • 2021-06-02
        • 1970-01-01
        • 1970-01-01
        • 2012-05-06
        • 2014-05-25
        • 2019-07-06
        • 1970-01-01
        相关资源
        最近更新 更多