主要内容

基于遗传算法的自定义数据类型优化

这个例子展示了如何使用遗传算法来最小化使用自定义数据类型的函数。遗传算法是定制的,用于解决旅行商问题。

旅行商问题

旅行商问题是一个城市数量有限且每个城市之间的旅行成本已知的优化问题。目标是找到销售人员要访问的所有城市的有序集合,使成本最小化。为了解决旅行推销员问题,我们需要列出城市位置和城市之间的距离或成本。

我们的推销员正在访问美国的一些城市。该文件usborder.mat包含变量中的美国地图xy,并在几何上简化了相同版本的变量映射xxyy

负载(“usborder.mat”“x”“是的”‘xx’‘yy’); 图(x,y,“颜色”“红色”); 持有在…上

我们将随机生成美国境内城市的位置。我们可以使用inpolygon功能是确保所有城市都在美国境内或非常接近美国边界。

城市=40;位置=0(城市,2);n=1;虽然(n<=城市)xp=兰特*1.5;yp=兰特;如果Inpolygon (xp,yp,xx,yy) locations(n,1) = xp;位置(n, 2) = yp;n = n + 1;结束结束绘图(位置(:,1),位置(:,2),“波”);

蓝色圆圈代表销售人员需要旅行和运送或提货的城市的位置。给定城市位置列表,我们可以计算所有城市的距离矩阵。

距离=零(城市);count1 = 1:城市,count2=1:count1,x1=位置(count1,1);y1=位置(计数1,2);x2=位置(计数2,1);y2=位置(计数2,2);距离(count1,count2)=sqrt((x1-x2)^2+(y1-y2)^2);距离(count2,count1)=距离(count1,count2);结束结束

为自定义数据类型自定义遗传算法

默认情况下,遗传算法求解器解决基于双和二进制字符串数据类型的优化问题。用于创建、交叉和变异的函数假设填充是双类型矩阵,或者在二进制字符串的情况下是逻辑矩阵。遗传算法求解器还可以处理涉及任意数据类型的优化问题。您可以为您的人口使用任何您喜欢的数据结构。例如,可以使用MATLAB®单元阵列指定自定义数据类型。为了使用遗传算法对于填充类型的单元格数组,您必须提供创建函数、交叉函数和变异函数,这些函数将用于您的数据类型,例如单元格数组。

旅行商问题的必要函数

本节介绍如何创建和注册三个必需的函数。旅行商问题人口中的个人是一个有序集,因此可以使用单元数组轻松表示人口。旅行商问题的自定义创建函数将创建一个单元数组,例如P,其中每个元素用排列向量表示一组有序的城市。也就是说,销售人员将按照中指定的顺序旅行P{我}.创建函数将返回一个大小相同的单元格数组PopulationSize

类型create_permutations.m
function pop = create_permutations(NVARS,FitnessFcn,options) % create_permutations创建一个置换种群。% POP = CREATE_PERMUTATION(NVARS,FITNESSFCN,OPTIONS)创建置换POP的填充%,每个置换POP的长度都是NVARS。% %函数的参数是% NVARS:变量的数量% FITNESSFCN:适应度函数% OPTIONS: GA使用的选项结构%n =据nvar;流行=细胞(totalPopulationSize, 1);for i = 1:totalPopulationSize pop{i} = randperm(n);结束

自定义交叉函数接受一个单元格数组,即总体,并返回一个单元格数组,即交叉产生的子元素。

类型crossover_permutation.m
函数xoverKids=交叉置换(父项、选项、NVAR、…FitnessFcn、thisScore、thisPopulation)%交叉置换旅行推销员的自定义交叉函数。%xoverKids=交叉置换(父项、选项、NVAR、%FitnessFcn、thisScore、thisPopulation)交叉父对象以生成%XoverChilds.%%函数的参数为%PARENTS:由选择函数选择的父对象%OPTIONS:从OPTIMOPTIONS创建的选项%NVARS:变量数%FITNESSFCN:适应度函数%STATE:GA解算器使用的状态结构%THISSCORE:当前人口的得分向量ation%THISPOPULATION:当前人口中的个体矩阵%Copyright 2004-2015 MathWorks,Inc.nKids=长度(父母)/2;xoverKids=单元格(nKids,1);%通常为零(nKids,NVARS);索引=1;对于i=1:nKids%,这里使用的是人口是单元格%数组的特殊知识。通常,这就是这个人口(父母(索引):;父母=这个群体{父母(索引)};索引=索引+2;%翻转父母的一部分1.p1=ceil((长度(父母)-1)*兰德);p2=p1+ceil((长度(父母)-p1-1)*兰德;孩子=父母;孩子(p1:p2)=翻转LR(孩子(孩子(p1:p2));xoverKids{i}=孩子;%正常情况下,xoverKids(i,:);结束

自定义突变函数接受一个个体(城市的有序集),并返回一个变异的有序集。

类型mutate_permutation.m
函数mutationChildren=mutate_permutation(父项、选项、NVAR、…FitnessFcn、状态、thisScore、thisPopulation、mutationRate)%mutate_permutation旅行推销员自定义变异函数,%MUTATIONCHILDREN=MUTATE_PERMUTATION(父项、选项、NVAR、%FITNESSFCN、状态、THISSCORE、THISPOPULATION、MUTATIONRATE)对%父项进行突变,以产生突变子项MUTATIONCHILDREN.%函数的参数为%PARENTS:选择函数选择的父对象%OPTIONS:从OPTIMOPTIONS创建的选项%NVARS:变量数%FITNESSFCN:适应度函数%STATE:GA解算器使用的状态结构%THISSCORE:当前总体分数向量%THISPOPULATION:当前总体中的个体矩阵人口%突变率:突变率%版权所有2004-2015 The MathWorks,Inc.%这里我们交换置换突变的两个元素Children=细胞(长度(父母),1);%通常为零(长度(父项),NVAR);对于i=1:length(parents)parent=thisPopulation{parents(i)};%正常情况下,这个群体(父母(i),:)p=ceil(父母的长度)*兰德(1,2));孩子=父母;子女(p(1))=父母(p(2));子女(p(2))=父母(p(1));突变儿童{i}=child;%正常情况下,突变子(i,:)结束

对于旅行商问题,我们也需要一个适应度函数。个体的适合度是在一组有序的城市中旅行的总距离。适应度函数也需要距离矩阵来计算总距离。

类型traveling_salesman_fitness.m
函数分数=旅行推销员健身(x,距离)%旅行推销员健身TSP的自定义健身函数。%scores=旅行推销员健身(x,距离)计算个人健身的百分比。健身是以x为单位的%有序城市集的总旅行距离。距离(A,B)是从城市%A到城市B的距离。%版权所有2004-2007 MathWorks,Inc.得分=0(大小(x,1),1);对于j=1:size(x,1)%这里使用了人口是一个单元格%数组的特殊知识。通常,这是pop(j,:);p=x{j};f=distance(p(end),p(1));对于i=2:length(p)f=f+distance(p(i-1),p(i));最终得分(j)=f;结束

遗传算法用一个参数调用适应度函数x,但我们的适应度函数有两个参数:x距离. 我们可以使用一个匿名函数来捕获附加参数的值,即距离矩阵。我们创建一个函数句柄适合性到接受一个输入的匿名函数x,但是traveling_salesman_fitnessx,距离。变量,距离有一个值时,函数句柄适合性,因此这些值由匿名函数捕获。

%前面定义的距离FitnessFcn = @(x) traveling_salesman_fitness(x,距离);

我们可以添加一个自定义绘图功能来绘制城市的位置和当前最佳路线。红色圆圈表示城市,蓝色线条表示两个城市之间的有效路径。

类型traveling_salesman_plot.m
功能状态=旅行推销员绘图(选项、状态、标志、位置)%旅行推销员绘图旅行推销员自定义绘图功能。%state=旅行推销员绘图(选项、状态、标志、位置)绘制城市%的位置和它们之间的连接路线。此函数特定于旅行商问题。%Copyright 2004-2006 MathWorks,Inc.如果strcmpi(标志,'init')加载('usborder.mat','x','y','xx','yy');结束图(x,y,'Color','red');轴([-0.1.5-0.2 1.2]);保持不变;[unused,i]=min(state.Score);基因型=状态。总体{i};绘图(位置(:,1),位置(:,2),'bo');绘图(位置(位置(基因型,1),位置(基因型,2));暂停

我们将再次使用匿名函数来创建一个匿名函数的函数句柄,该匿名函数调用旅行推销员图加上额外的论点位置

%先前定义的位置My_plot = @(options,state,flag)...国家、国旗、地点);

遗传算法选项设置

首先,我们将创建一个选项容器来指示自定义数据类型和填充范围。

选择= optimoptions (@ga,“PopulationType”“自定义”“InitialPopulationRange”...[1;城市];

我们选择我们已经创建的自定义创建、交叉、变异和绘图功能,以及设置一些停止条件。

选择= optimoptions(选项,“CreationFcn”,@create_置换,...“交叉路口”@crossover_permutation,...“突变FCN”@mutate_permutation,...“PlotFcn”我的"阴谋",,...“MaxGenerations”, 500,“PopulationSize”,60,...“超级世代”, 200,“UseVectorized”,真正的);

最后,用问题信息调用遗传算法。

numberOfVariables =城市;[x, fval原因,输出]=...ga(FitnessFcn,numberOfVariables,[]、[]、[]、[]、[]、[]、[]、[]、[]、[]、选项)
优化已终止:超过最大生成数。x=1x1单元数组{1x40 double}fval=5.3846原因=0输出=struct带字段:problemtype:'Unconstraint'rngstate:[1x1 struct]代数:500 funccount:28563消息:“优化已终止:超出最大代数。”maxconstraint:[]hybridflag:[]

该图显示了蓝色圆圈中城市的位置,以及通过遗传算法找到的推销员将要旅行的路径。推销员可以从路线的两端出发,然后在终点返回出发城市回家。

相关话题