一,介绍:
TSA树种优化算法(TSA),是一种新型的演化算法,该算法是模拟大树通过种子进行繁衍的过程。Kiran在2015年提出了TSA算法。以下就是套话,该算法的收敛速度快,收敛精度高,等等....这几乎是每一种新型的优化算法提出来都会说的。
但是TSA相对于传统的GA,PSO和新型的WOA等算法相比确实有一些优势,这个后面会提到。
二,流程
先贴一张论文中给出的流程图
感觉有点困难?没关系,下面开始逐字逐句的讲解:
- 初始化种群及相关参数:
种群中的个数(N),
种群中个体的维度(D),
进化方式的概率(ST(现在看不懂没关系,后面马上会提及)),
设置终止条件(这里的终止条件和其他的进化算法不同,不是通过迭代次数来控制结束的)。
生成随机个体,生成方式为:,
按照这种方法就生成N组个体 - 设置适应度函数,求出对应的适应值,挑选出适应度值最小的个体:
- For 所有的树:
- 决定当前的树产生多少种子(这里有一套规则,后面会讲解)
- For 所有的种子
- For 所有的维度
- IF rand < ST(之前设置的一个参数):
- (S为种子的个体,T为树的个体,alpha为提前设置的参数,i为当前的种子,j 为当前维度,B为当前记录最好的个体,r为随机数)
- ELSE
- (S为种子的个体,T为树的个体,alpha为提前设置的参数,i为当前的种子,j 为当前维度
- IF rand < ST(之前设置的一个参数):
- For 所有的维度
- 选择最优的种子,如果这个种子的适应度优于当前的树,则替代当前的树
- 所有的树迭代完之后,挑选最优的个体。如果该最优个体优于B,则进行替换
- 看是否达到终止条件(这里的终止条件不是迭代次数,而是看产生的种子个数是否达到一定的量,在代码中会详细的讲到),如果未达到终止条件,则返回第二步
- 输出最优个体
整个流程还是相当简单的,TSA的算法的收敛效果也确实比较优秀。
三,代码(matlab)
一,matlab代码
function [minimum,bestParams]=TSA(iw,maxrun,N,D,ST,maxFEs,dmin,dmax,func_num)
iterdosyaadi=strcat('F',num2str(func_num),'_IW',num2str(iw*10),'_N',num2str(N),'_D',num2str(D),'_',num2str(maxFEs),'_iters');
dosyaadi=strcat('F',num2str(func_num),'_IW',num2str(iw*10),'_N',num2str(N),'_D',num2str(D),'_',num2str(maxFEs));
% low和high是控制每一代树的产生的种子的上限和下限
low=ceil(N*0.1);
high=ceil(N*0.25);
iterasyonlar=zeros(maxrun,maxFEs);
for run=1:maxrun
% 重复的次数
rand('state',sum(100*clock));
trees=zeros(N,D);
obj_trees=zeros(1,N);
% 初始化个体
for i=1:N
for j=1:D
trees(i,j)=dmin+(dmax-dmin)*rand;
end;
obj_trees(i)=bildiriseti(trees(i,:),func_num);
end
FEs = N;
[minimum]=min(obj_trees);
mins=zeros(1,maxFEs);
iter=0;
while(FEs<=maxFEs)
%% 相当于是挑选选中的树木,对数目产生的seed进行处理
iter=iter+1;
%% 对种群中的每一颗树进行遍历
for i=1:N
ns=fix(low+(high-low)*rand)+1;
FEs = FEs + ns;
if(ns>high)
ns=high;
end;
seeds=zeros(ns,D);
obj_seeds=zeros(1,ns);
[minimum,min_indis]=min(obj_trees);
bestParams=trees(min_indis,:);
%% 对每一颗树产生种子进行更新
for j=1:ns
komsu=fix(rand*N)+1;
while(i==komsu) % 选中的种子不能和当前的树相同
komsu=fix(rand*N)+1;
end
seeds(j,:)=trees(j,:);% 将这个树的直接赋值给这个种子
for d=1:D
if(rand<ST)
seeds(j,d)=iw*trees(i,d)+(bestParams(d)-trees(komsu,d))*(rand-0.5)*2;
%在这里可以看出seeds的特点,种群的每一维度在更新的时候不收影响
if(seeds(j,d)>dmax)
seeds(j,d)=dmax;
end;
if(seeds(j,d)<dmin)
seeds(j,d)=dmin;
end;
else
seeds(j,d)=iw*trees(i,d)+(trees(i,d)-trees(komsu,d))*(rand-0.5)*2;
if(seeds(j,d)>dmax)
seeds(j,d)=dmax;
end;
if(seeds(j,d)<dmin)
seeds(j,d)=dmin;
end;
end;
end;
obj_seeds(j)=bildiriseti(seeds(j,:),func_num);
end;
[mintohum,mintohum_indis]=min(obj_seeds);
if(mintohum<obj_trees(i))
trees(i,:)=seeds(mintohum_indis,:);
obj_trees(i)=mintohum;
end;
end;
[min_tree,min_tree_index]=min(obj_trees);
if(min_tree<minimum)
minimum=min_tree;
bestParams=trees(min_tree_index,:);
end;
iterasyonlar(run,iter)=minimum;
save(iterdosyaadi,'iterasyonlar');
fprintf('Iter=%d .... min=%g .... FES=%d .... \n',iter,minimum,FEs);
end;
fprintf('Run=%d .... min=%g ....\n',run,minimum);
dosya(run,1)=minimum;
end;
dosya(maxrun+1,1)=mean(dosya(1:maxrun,1));
dosya(maxrun+1,2)=std(dosya(1:maxrun,1));
dosya(maxrun+1,3)=median(dosya(1:maxrun,1));
dosya(maxrun+1,4)=min(dosya(1:maxrun,1));
dosya(maxrun+1,5)=max(dosya(1:maxrun,1));
save(dosyaadi,'dosya');
end
参数讲解:
iw:种子更新时,位于的系数
maxrun: 算法执行的重复次数(这个不是迭代次数,也不是终止条件)
N:种群的大小 D:个体的维度
maxFEs :在这里,设置maxFEs = D * 10000。这里就是真正的中止条件,所有在树的迭代过程中,产生的种子数如果达到了maxFEs,则停止产生,中止迭代
dmin,dmax:维度的限制
在代码中变量均已经做出相关的解释。
二,python代码
import numpy as np
def func(x):
return np.sum(x ** 2)
def TSA(iw, maxrun, N, D, ST, maxFEs, dmin, dmax):
low = int(N * 0.1)
high = int(N * 0.25)
iterasyonlar = np.zeros((maxrun, maxFEs)) # 存放每一个重复的循环下,种子的适应度
dosya = np.zeros((maxrun, 1))
for run in range(maxrun):
np.random.seed(0)
# 重复的次数
trees = np.zeros((N, D))
obj_trees = np.zeros((N, 1)) # 存放每个个体的目标值
for i in range(N):
for j in range(D):
trees[i, j] = dmin + np.random.rand() * (dmax - dmin)
obj_trees[i] = func(trees[i, :])
FEs = N # 因为当前已经产生了N个个体
minimum = np.min(obj_trees)
iter1 = 0
while (FEs <= maxFEs):
iter1 = iter1 + 1
for i in range(N):
# i是树木
ns = int(low + (high - low) * np.random.rand()) + 1
FEs = FEs + ns
if ns > high:
ns = high
seeds = np.zeros((ns, D)) # 记录当前的种子的具体形式
obj_seeds = np.zeros((ns, 1))
minimum, min_index = np.min(obj_trees), np.argmin(obj_trees)
bestParams = trees[min_index, :]
for j in range(ns):
# j 是种子
komus = int(np.random.rand() * N) + 1
while komus == i or komus >=N or komus < 0 :
komus = int(np.random.rand() * N) + 1
seeds[j, :] = trees[j, :]
for d in range(D):
if np.random.rand() < ST:
seeds[j, d] = iw * trees[i, d] + (bestParams[d] - trees[komus, d]) * (
np.random.rand() - 0.5) * 2
if seeds[j, d] > dmax:
seeds[j, d] = dmax
if seeds[j, d] < dmin:
seeds[j, d] = dmin
else:
seeds[j, d] = iw * trees[i, d] + (trees[i, d] - trees[komus, d]) * (
np.random.rand() - 0.5) * 2
if seeds[j, d] > dmax:
seeds[j, d] = dmax
if seeds[j, d] < dmin:
seeds[j, d] = dmin
obj_seeds[j] = func(seeds[j, :])
mini_seeds, mini_seeds_ind = np.min(obj_seeds), np.argmin(obj_seeds)
if mini_seeds < obj_trees[i]:
trees[i, :] = seeds[mini_seeds_ind, :]
obj_trees[i] = mini_seeds
min_tree, min_tree_index = np.min(obj_trees), np.argmin(obj_trees)
if min_tree < minimum:
minimum = min_tree
bestParams = trees[min_tree_index, :]
iterasyonlar[run, iter1] = minimum
print('Iter={} .... min={} .... FES={} .... \n'.format(iter1, minimum, FEs))
print('Run={} .... min={} ....\n'.format(run, minimum))
dosya[run] = minimum
print(dosya)
return np.min(dosya), bestParams
TSA(1,30,10,10,0.1,10*10000,-10,10)
代码流程和matlab的流程差不多,不做赘述。
思考:
TSA本身的有点很明显:在处理个体的不同维度时,它可以做到维度之间相互独立。什么意思呢?就比如我在做一个优化问题时,要求第1维的单位为1,范围在[-10,10],第2维的精度为0.00001,范围为[0.1,0.00001]。以GA为例,在处理时存在交叉等操作,就会导致不同维度之间产生干扰,需要设计更加复杂的编码方式。