├── SSA2017_new.py ├── DE.py ├── PSO.py ├── CSA.py ├── SCA.py ├── GA.py ├── SSA2017.py ├── test_function_20221018.py ├── WPS.py ├── GSA.py ├── SBO.py ├── README.md ├── FA.py ├── SSA2020.py ├── test_function.py └── WPA.py /SSA2017_new.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import test_function 4 | 5 | class SA: 6 | def __init__(self,iterations,n_dim,lb,ub,pop_size,target_function): 7 | self.iterations=iterations 8 | self.n_dim=n_dim 9 | self.lb=lb 10 | self.ub=ub 11 | self.pop_size=pop_size 12 | self.target_function=target_function 13 | 14 | self.X=np.random.uniform() 15 | self.X=np.random.uniform(lb,ub,(pop_size,n_dim+1)) 16 | for i in range(len(self.X)): 17 | self.X[i][-1] = self.target_function(self.X[i][:-1]) 18 | self.X=sorted(self.X,key=lambda x: x[-1]) 19 | self.g_best=self.X[0] 20 | self.gbest_Y_history=[self.X[0][-1]] 21 | 22 | def run(self,visible=False): 23 | for iter in range(self.iterations): 24 | c1=2*np.power(np.e,-(4*iter/self.iterations)**2) 25 | self.X[0]=self.g_best+np.random.uniform(-1,1)*c1*(np.random.uniform()*(self.ub-self.lb)+self.lb) 26 | self.X[0][:-1] = np.clip(self.X[0][:-1], self.lb, self.ub) 27 | self.X[0][-1] = self.target_function(self.X[0][:-1]) 28 | for i in range(1,self.pop_size): 29 | self.X[i]=0.5*(self.X[i]+self.X[i-1]) 30 | self.X[i][-1] = self.target_function(self.X[i][:-1]) 31 | self.X=sorted(self.X,key=lambda x: x[-1]) 32 | if self.g_best[-1]>self.X[0][-1]: 33 | self.g_best=self.X[0] 34 | self.gbest_Y_history.append(self.g_best[-1]) 35 | if visible: 36 | print(self.X[0]) 37 | 38 | def result(self): 39 | return self.X[0] 40 | 41 | def convergence_curve(self): 42 | plt.plot(self.gbest_Y_history) 43 | plt.yscale('log') 44 | plt.show() 45 | 46 | if __name__ == '__main__': 47 | test=SA(iterations=1000,n_dim=2,lb=-10,ub=10,pop_size=50,target_function=test_function.F6) 48 | test.run(visible=True) 49 | print("result:{}".format(test.result())) 50 | test.convergence_curve() 51 | -------------------------------------------------------------------------------- /DE.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import random 3 | import copy 4 | import test_function 5 | 6 | class DE(): 7 | def __init__(self, iterations, n_dim, lb, ub, pop_size, target_function,mutate_factor,cross_rate): 8 | self.iterations = iterations 9 | self.n_dim = n_dim 10 | self.lb = lb 11 | self.ub = ub 12 | self.pop_size = pop_size 13 | self.target_function = target_function 14 | self.mutate_factor=mutate_factor 15 | self.cross_rate=cross_rate 16 | 17 | def particle_init(self): 18 | self.particles = [[] for i in range(self.pop_size)] 19 | for i in range(self.pop_size): 20 | for j in range(self.n_dim): 21 | self.particles[i].append(random.uniform(self.lb, self.ub)) 22 | self.particles[i].append(self.target_function(self.particles[i])) 23 | if self.g_best[-1] > self.particles[i][-1]: 24 | self.g_best = copy.deepcopy(self.particles[i]) 25 | 26 | def mutate_and_cross(self): 27 | for i in range(self.pop_size): 28 | target_1=random.randint(0,self.pop_size-1) 29 | while(target_1==i): 30 | target_1=random.randint(0,self.pop_size-1) 31 | target_2=random.randint(0,self.pop_size-1) 32 | while(target_2==i or target_2==target_1): 33 | target_2 = random.randint(0, self.pop_size-1) 34 | target_3=random.randint(0,self.pop_size-1) 35 | while(target_3==i or target_3==target_1 or target_3==target_2): 36 | target_3 = random.randint(0, self.pop_size-1) 37 | target=[] 38 | for j in range(self.n_dim): 39 | target.append(self.particles[target_1][j]+self.mutate_factor*(self.particles[target_2][j]-self.particles[target_3][j])) 40 | if random.random()>self.cross_rate: 41 | target[j]=self.particles[i][j] 42 | if target[j]self.ub: 45 | target[j]=self.ub 46 | target.append(self.target_function(target)) 47 | if self.particles[i][-1]>target[-1]: 48 | self.particles[i]=target 49 | if self.g_best[-1] > self.particles[i][-1]: 50 | self.g_best = copy.deepcopy(self.particles[i]) 51 | 52 | def run(self): 53 | self.g_best = [0 for i in range(self.pop_size)] 54 | self.g_best.append(float('inf')) 55 | self.g_best_hist = [] 56 | self.particle_init() 57 | for i in range(self.iterations): 58 | self.mutate_and_cross() 59 | self.g_best_hist.append(self.g_best[-1]) 60 | 61 | def result(self): 62 | return self.g_best 63 | 64 | def convergence_curve(self): 65 | plt.plot(self.g_best_hist) 66 | plt.yscale('log') 67 | plt.show() 68 | 69 | if __name__ == '__main__': 70 | test = DE(iterations=500, n_dim=30, lb=-500, ub=500, pop_size=50, target_function=test_function.F1, mutate_factor=0.3,cross_rate=0.5) 71 | test.run() 72 | result = test.result() 73 | test.convergence_curve() 74 | print(result) -------------------------------------------------------------------------------- /PSO.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2021/12/15 15:57 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : PSO.py 7 | 8 | """ 9 | Ref:https://github.com/guofei9987/scikit-opt 10 | 已经有了很多可以调用粒子群算法的库,但是在高维情形下的寻优效果很差,所以决定自己再写一个 11 | """ 12 | 13 | import numpy as np 14 | import matplotlib.pyplot as plt 15 | import math 16 | import test_function 17 | 18 | class PSO(): 19 | def __init__(self, func, n_dim=None, pop=40, max_iter=150, lb=-1e5, ub=1e5, w=0.8, c1=0.5, c2=0.5): 20 | self.func = func 21 | self.w = w # inertia 22 | self.cp, self.cg = c1, c2 # parameters to control personal best, global best respectively 23 | self.pop = pop # number of particles 24 | self.n_dim = n_dim # dimension of particles, which is the number of variables of func 25 | self.max_iter = max_iter # max iter 26 | 27 | self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim) 28 | assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' 29 | assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound' 30 | 31 | self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) 32 | v_high = self.ub - self.lb 33 | self.V = np.random.uniform(low=-v_high, high=v_high, size=(self.pop, self.n_dim)) # speed of particles 34 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles 35 | 36 | self.pbest_x = self.X.copy() # personal best location of every particle in history 37 | self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history 38 | self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles 39 | self.gbest_y = np.inf # global best y for all particles 40 | self.gbest_y_hist = [] # gbest_y of every iteration 41 | self.update_gbest() 42 | 43 | def update_pbest(self): 44 | ''' 45 | personal best 46 | :return: 47 | ''' 48 | for i in range(len(self.Y)): 49 | if self.pbest_y[i] > self.Y[i]: 50 | self.pbest_x[i] = self.X[i] 51 | self.pbest_y[i] = self.Y[i] 52 | 53 | def update_gbest(self): 54 | ''' 55 | global best 56 | :return: 57 | ''' 58 | idx_min = self.pbest_y.index(min(self.pbest_y)) 59 | if self.gbest_y > self.pbest_y[idx_min]: 60 | self.gbest_x = self.X[idx_min, :].copy() 61 | self.gbest_y = self.pbest_y[idx_min] 62 | 63 | def update_V(self): 64 | r1 = np.random.rand(self.pop, self.n_dim) 65 | r2 = np.random.rand(self.pop, self.n_dim) 66 | self.V = self.w * self.V + self.cp * r1 * (self.pbest_x - self.X) + self.cg * r2 * (self.gbest_x - self.X) 67 | 68 | def update(self): 69 | for i in range(self.pop): 70 | self.X[i] += self.V[i] 71 | self.X = np.clip(self.X, self.lb, self.ub) 72 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] 73 | 74 | def run(self): 75 | for iter_no in range(self.max_iter): 76 | self.update_V() 77 | self.update() 78 | self.update_pbest() 79 | self.update_gbest() 80 | self.gbest_y_hist.append(self.gbest_y) 81 | self.best_x, self.best_y = self.gbest_x, self.gbest_y 82 | return self.best_x, self.best_y 83 | 84 | if __name__ == '__main__': 85 | n_dim = 30 86 | lb = [-100 for i in range(n_dim)] 87 | ub = [100 for i in range(n_dim)] 88 | demo_func = test_function.fu2 89 | pop_size = 100 90 | max_iter = 1000 91 | pso = PSO(func=demo_func, n_dim=n_dim, pop=100, max_iter=1000, lb=lb, ub=ub, w=0.8, c1=0.5, c2=0.5) 92 | best_x, bext_y = pso.run() 93 | print(f'{demo_func(pso.gbest_x)}\t{pso.gbest_x}') 94 | # plt.plot(pso.gbest_y_hist) 95 | # plt.show() -------------------------------------------------------------------------------- /CSA.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2021/12/3 15:23 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : CSA.py 7 | 8 | """ 9 | Ref: 10 | [1] https://github.com/Luan-Michel/CrowSearchAlgorithmPython/blob/master 11 | # /CrowSearchAlgorithm.py 12 | [2] Alireza Askarzadeh, Anovel metaheuristic method for solving constrained 13 | # engineering optimization problems: Crow search algorithm, Computers & 14 | # Structures, Vol. 169, 1-12, 2016. 15 | """ 16 | 17 | import random # random Function 18 | import numpy as np # numpy operations 19 | import matplotlib.pyplot as plt 20 | import math # ceil function 21 | import test_function 22 | 23 | class CSA(): 24 | def __init__(self, pop_size=5, n_dim=2, ap=0.1, lb=-1e5, ub=1e5, max_iter=20, func=None): 25 | self.pop = pop_size 26 | self.n_dim = n_dim 27 | self.ap = ap # 感知概率 28 | self.func = func 29 | self.max_iter = max_iter # max iter 30 | self.fly_length = [2 for _ in range(self.n_dim)] # 飞行距离,可以考虑是否采用莱维飞行或者随迭代次数改变 31 | # 或许也和变量维数相关 32 | self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim) 33 | assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' 34 | assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound' 35 | 36 | self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) 37 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles 38 | 39 | self.pbest_x = self.X.copy() # personal best location of every particle in history 40 | self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history 41 | self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles 42 | self.gbest_y = np.inf # global best y for all particles 43 | self.gbest_y_hist = [] # gbest_y of every iteration 44 | self.update_gbest() 45 | 46 | def update_pbest(self): 47 | ''' 48 | personal best 49 | :return: 50 | ''' 51 | for i in range(len(self.Y)): 52 | if self.pbest_y[i] > self.Y[i]: 53 | self.pbest_x[i] = self.X[i] 54 | self.pbest_y[i] = self.Y[i] 55 | 56 | def update_gbest(self): 57 | ''' 58 | global best 59 | :return: 60 | ''' 61 | idx_min = self.pbest_y.index(min(self.pbest_y)) 62 | if self.gbest_y > self.pbest_y[idx_min]: 63 | self.gbest_x = self.X[idx_min, :].copy() 64 | self.gbest_y = self.pbest_y[idx_min] 65 | 66 | def update(self): 67 | num = np.array([random.randint(0, self.pop - 1) for _ in range(self.pop)]) # Generation of random candidate crows for following (chasing) 68 | for i in range(self.pop): 69 | if (random.random() > self.ap): 70 | for j in range(self.n_dim): 71 | self.X[(i, j)] = self.X[(i, j)] + self.fly_length[j] * ((random.random()) * (self.pbest_x[(num[i], j)] - self.X[(i, j)])) 72 | else: 73 | for j in range(self.n_dim): # 随机生成或许可以考虑采用莱维飞行 74 | self.X[(i, j)] = self.lb[j] - (self.lb[j] - self.ub[j]) * random.random() 75 | self.X = np.clip(self.X, self.lb, self.ub) 76 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # Function for fitness evaluation of new solutions 77 | 78 | def run(self): 79 | for iter in range(self.max_iter): 80 | self.update() 81 | self.update_pbest() 82 | self.update_gbest() 83 | self.gbest_y_hist.append(self.gbest_y) 84 | self.best_x, self.best_y = self.gbest_x, self.gbest_y 85 | return self.best_x, self.best_y 86 | 87 | if __name__ == '__main__': 88 | # todo(xionglei@sjtu.edu.cn): 哪里有问题,复现的寻优效果很差 89 | n_dim = 30 90 | lb = [-100 for i in range(n_dim)] 91 | ub = [100 for i in range(n_dim)] 92 | demo_func = test_function.fu2 93 | pop_size = 100 94 | max_iter = 1000 95 | csa = CSA(n_dim=n_dim, pop_size=pop_size, max_iter=max_iter, lb=lb, ub=ub, func=demo_func) 96 | best_x, bext_y = csa.run() 97 | print(f'{demo_func(csa.gbest_x)}\t{csa.gbest_x}') 98 | plt.plot(csa.gbest_y_hist) 99 | plt.show() 100 | 101 | -------------------------------------------------------------------------------- /SCA.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2021/12/8 14:20 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : SCA_new.py 7 | 8 | """ 9 | Ref:https://github.com/luizaes/sca-algorithm 10 | S. Mirjalili, SCA: A Sine Cosine Algorithm for Solving Optimization Problems, Knowledge-based Systems, in press, 2015, DOI: http://dx.doi.org/10.1016/j.knosys.2015.12.022 11 | """ 12 | 13 | import numpy as np 14 | import random 15 | import math 16 | import matplotlib.pyplot as plt 17 | import test_function 18 | 19 | class sca(): 20 | def __init__(self, pop_size=5, n_dim=2, a=2, lb=-1e5, ub=1e5, max_iter=20, func=None): 21 | self.pop = pop_size 22 | self.n_dim = n_dim 23 | self.a = a # 感知概率 24 | self.func = func 25 | self.max_iter = max_iter # max iter 26 | 27 | self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim) 28 | assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' 29 | assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound' 30 | 31 | self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) 32 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles 33 | 34 | self.pbest_x = self.X.copy() # personal best location of every particle in history 35 | self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history 36 | self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles 37 | self.gbest_y = np.inf # global best y for all particles 38 | self.gbest_y_hist = [] # gbest_y of every iteration 39 | self.update_gbest() 40 | 41 | def update_pbest(self): 42 | ''' 43 | personal best 44 | :return: 45 | ''' 46 | for i in range(len(self.Y)): 47 | if self.pbest_y[i] > self.Y[i]: 48 | self.pbest_x[i] = self.X[i] 49 | self.pbest_y[i] = self.Y[i] 50 | 51 | 52 | def update_gbest(self): 53 | ''' 54 | global best 55 | :return: 56 | ''' 57 | idx_min = self.pbest_y.index(min(self.pbest_y)) 58 | if self.gbest_y > self.pbest_y[idx_min]: 59 | self.gbest_x = self.X[idx_min, :].copy() 60 | self.gbest_y = self.pbest_y[idx_min] 61 | 62 | def update(self, i): 63 | r1 = self.a - i * ((self.a) / self.max_iter) 64 | for j in range(self.pop): 65 | for k in range(self.n_dim): 66 | r2 = 2 * math.pi * random.uniform(0.0, 1.0) 67 | r3 = 2 * random.uniform(0.0, 1.0) 68 | r4 = random.uniform(0.0, 1.0) 69 | if r4 < 0.5: 70 | try: 71 | self.X[j][k] = self.X[j][k] + (r1 * math.sin(r2) * abs(r3 * self.gbest_x[k] - self.X[j][k])) 72 | except: 73 | self.X[j][k] = self.X[j][k] + (r1 * math.sin(r2) * abs(r3 * self.gbest_x[0][k] - self.X[j][k])) 74 | else: 75 | try: 76 | self.X[j][k] = self.X[j][k] + (r1 * math.cos(r2) * abs(r3 * self.gbest_x[k] - self.X[j][k])) 77 | except: 78 | self.X[j][k] = self.X[j][k] + (r1 * math.cos(r2) * abs(r3 * self.gbest_x[0][k] - self.X[j][k])) 79 | self.X = np.clip(self.X, self.lb, self.ub) 80 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # Function for fitness evaluation of new solutions 81 | 82 | 83 | def run(self): 84 | for i in range(self.max_iter): 85 | self.update(i) 86 | self.update_pbest() 87 | self.update_gbest() 88 | self.gbest_y_hist.append(self.gbest_y) 89 | self.best_x, self.best_y = self.gbest_x, self.gbest_y 90 | return self.best_x, self.best_y 91 | 92 | if __name__ == '__main__': 93 | n_dim = 2 94 | lb = [-512 for i in range(n_dim)] 95 | ub = [512 for i in range(n_dim)] 96 | demo_func = test_function.f23 97 | sca = sca(n_dim=2, pop_size=40, max_iter=150, lb=lb, ub=ub, func=demo_func) 98 | sca.run() 99 | print('best_x is ', sca.gbest_x, 'best_y is', sca.gbest_y) 100 | print(f'{demo_func(sca.gbest_x)}\t{sca.gbest_x}') 101 | plt.plot(sca.gbest_y_hist) 102 | plt.show() 103 | -------------------------------------------------------------------------------- /GA.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import test_function 3 | import matplotlib.pyplot as plt 4 | import random 5 | 6 | class GA(): 7 | 8 | def __init__(self,iterations,n_dim,lb,ub,pop_size,target_function,retain_rate,random_select_rate,mutation_probability): 9 | self.iterations=iterations 10 | self.n_dim=n_dim 11 | self.lb=lb 12 | self.ub=ub 13 | self.pop_size=pop_size 14 | self.target_function=target_function 15 | self.retain_rate=retain_rate 16 | self.random_select_rate=random_select_rate 17 | self.mutation_probability=mutation_probability 18 | 19 | def particle_init(self): 20 | self.particle=[[] for i in range(self.pop_size)] 21 | self.g_best=[0 for i in range(self.n_dim)] 22 | self.g_best.append(float('inf')) 23 | for i in range(self.pop_size): 24 | for j in range(self.n_dim): 25 | self.particle[i].append(random.uniform(self.lb,self.ub)) 26 | self.particle[i].append(self.target_function(self.particle[i])) 27 | if self.g_best[-1]>self.particle[i][-1]: 28 | self.g_best = copy.deepcopy(self.particle[i]) 29 | self.chosen_probability=[0 for i in range(self.pop_size)] 30 | self.calculate_chosen_probability() 31 | 32 | def calculate_chosen_probability(self): 33 | fitness=0 34 | 35 | for i in range(self.pop_size): 36 | fitness+=self.particle[i][-1] 37 | for i in range(self.pop_size): 38 | self.chosen_probability[i]=self.particle[i][-1]/fitness 39 | 40 | def selction(self): 41 | fitness=[] 42 | for i in self.particle: 43 | fitness.append(i[-1]) 44 | fitness.sort(reverse=True) 45 | retain_criteria=fitness[int(self.pop_size*self.retain_rate)] 46 | parents=[] 47 | for i in range(self.pop_size): 48 | if self.particle[i][-1]<=retain_criteria or random.random()self.particle[-1][-1]: 64 | self.g_best=copy.deepcopy(self.particle[-1]) 65 | 66 | 67 | def mutate(self,iteration): 68 | for i in range(int(self.pop_size*self.retain_rate),self.pop_size): 69 | if random.random()self.ub: 73 | self.particle[i][j]=self.ub 74 | if self.particle[i][j]self.particle[i][-1]: 78 | self.g_best=copy.deepcopy(self.particle[i]) 79 | 80 | def run(self): 81 | self.particle_init() 82 | self.g_best_hist=[self.g_best[-1]] 83 | for i in range(self.iterations): 84 | self.calculate_chosen_probability() 85 | self.selction() 86 | self.cross() 87 | self.mutate(i) 88 | self.g_best_hist.append(self.g_best[-1]) 89 | 90 | def result(self): 91 | return self.g_best 92 | 93 | def convergence_curve(self): 94 | plt.plot(self.g_best_hist) 95 | plt.yscale('log') 96 | plt.show() 97 | 98 | if __name__ == '__main__': 99 | 100 | test=GA(iterations=1000,n_dim=1,lb=-500,ub=500,pop_size=50,target_function=function,retain_rate=0.3,random_select_rate=0.2,mutation_probability=0.8) 101 | test.run() 102 | result=test.result() 103 | test.convergence_curve() 104 | print(result) -------------------------------------------------------------------------------- /SSA2017.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2021/12/5 15:39 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : SSA2017.py 7 | 8 | ############################################################################ 9 | 10 | # Ref: Salp Swarm Algorithm: A bio-inspired optimizer for engineering design problems.pdf 11 | 12 | ############################################################################ 13 | 14 | # Required Libraries 15 | import numpy as np 16 | import math 17 | import random 18 | import os 19 | import matplotlib.pyplot as plt 20 | import test_function 21 | 22 | class salp_swarm_algorithm(): 23 | def __init__(self, pop_size=50, n_dim=2, max_iter=150, lb=[-5,-5], ub=[5,5], func=None): 24 | self.pop = pop_size 25 | self.lb = lb 26 | self.ub = ub 27 | self.func = func 28 | self.n_dim = n_dim 29 | self.max_iter = max_iter 30 | 31 | 32 | self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) 33 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles 34 | self.pbest_x = self.X.copy() # personal best location of every particle in history 35 | self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history 36 | self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles 37 | self.gbest_y = np.inf # global best y for all particles 38 | self.gbest_y_hist = [] # gbest_y of every iteration 39 | self.update_pbest() 40 | self.update_gbest() 41 | 42 | def update_pbest(self): 43 | ''' 44 | personal best 45 | :return: 46 | ''' 47 | for i in range(len(self.Y)): 48 | if self.pbest_y[i] > self.Y[i]: 49 | self.pbest_x[i] = self.X[i] 50 | self.pbest_y[i] = self.Y[i] 51 | 52 | def update_gbest(self): 53 | ''' 54 | global best 55 | :return: 56 | ''' 57 | idx_min = self.pbest_y.index(min(self.pbest_y)) 58 | if self.gbest_y > self.pbest_y[idx_min]: 59 | self.gbest_x = self.X[idx_min, :].copy() 60 | self.gbest_y = self.pbest_y[idx_min] 61 | 62 | 63 | 64 | # Function: Updtade Position 65 | def update_position(self, c1): 66 | for i in range(0, self.pop): 67 | if (i <= self.pop / 2): # 领导者比例 68 | for j in range(0, self.n_dim): 69 | c2 = int.from_bytes(os.urandom(8), byteorder="big") / ((1 << 64) - 1) 70 | c3 = int.from_bytes(os.urandom(8), byteorder="big") / ((1 << 64) - 1) 71 | if (c3 >= 0.5): # c3 < 0.5 72 | try: 73 | self.X[i, j] = np.clip((self.gbest_x[0][j] + c1 * ((self.ub[j] - self.lb[j]) * c2 + self.lb[j])), self.lb[j], self.ub[j]) 74 | except: 75 | self.X[i, j] = np.clip((self.gbest_x[j] + c1 * ((self.ub[j] - self.lb[j]) * c2 + self.lb[j])), self.lb[j], self.ub[j]) 76 | else: 77 | try: 78 | self.X[i, j] = np.clip((self.gbest_x[0][j] - c1 * ((self.ub[j] - self.lb[j]) * c2 + self.lb[j])), self.lb[j], self.ub[j]) 79 | except: 80 | self.X[i, j] = np.clip((self.gbest_x[j] - c1 * ((self.ub[j] - self.lb[j]) * c2 + self.lb[j])), self.lb[j], self.ub[j]) 81 | else: # 追随者比例 82 | for j in range(0, self.n_dim): 83 | self.X[i, j] = np.clip(((self.X[i - 1, j] + self.X[i, j]) / 2), self.lb[j], self.ub[j]) 84 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles 85 | 86 | def run(self): 87 | for i in range(self.max_iter): 88 | c1 = 2 * math.exp(-(4 * ((i+1) / self.max_iter)) ** 2) 89 | self.update_position(c1) 90 | self.update_pbest() 91 | self.update_gbest() 92 | self.gbest_y_hist.append(self.gbest_y) 93 | self.best_x, self.best_y = self.gbest_x, self.gbest_y 94 | return self.best_x, self.best_y 95 | 96 | 97 | if __name__ == '__main__': 98 | n_dim = 30 99 | lb = [-5 for i in range(n_dim)] 100 | ub = [5 for i in range(n_dim)] 101 | demo_func = test_function.fu1 102 | ssa = salp_swarm_algorithm(pop_size=50, n_dim=n_dim, max_iter=150, lb=lb, ub=ub, func=demo_func) 103 | ssa.run() 104 | print('best_x is ', ssa.gbest_x, 'best_y is', ssa.gbest_y) 105 | print(f'{demo_func(ssa.gbest_x)}\t{ssa.gbest_x}') 106 | plt.plot(ssa.gbest_y_hist) 107 | plt.show() 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /test_function_20221018.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2022/10/18 13:33 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : test_function_20221018.py 7 | 8 | ''' 9 | This file contains test functions in Xue's paper[1], including unimodal test functions(F1~F7), multimodal test functions(F8~F11) and fixed-dimension test functions(F13~F16). 10 | Multimodal test function(F12 is the function fm5 in the test_function.py file) may have errors and it's not included in this file. 11 | Fixed-test functions(F17~F19) are not included in this file, as the coefficient in F17~F19 isn't found. 12 | 13 | There are seven unimodal test functions, four multimodal test functions and four fixed-test functions. 14 | Test functions in this file may appear in the file(test_function,py), too. 15 | 16 | [1] Xue Jiankai, Shen Bo. A novel swarm intelligence optimization approach: sparrow search algorithm[J]. Systems Science & Control Engineering, 2020, 8(1): 22-34. 17 | ''' 18 | import math 19 | from scipy.stats import norm 20 | 21 | # Unimodal test functions 22 | def F1(x): 23 | # xi ∈ [-100, 100] and min is 0 24 | s1 = 0 25 | for i in range(len(x)): 26 | s1 += (x[i] ** 2) 27 | return s1 28 | 29 | def F2(x): 30 | # xi ∈ [-10, 10] and min is 0 31 | s1 = 0 32 | s2 = 1 33 | for i in range(len(x)): 34 | s1 += abs(x[i]) 35 | s2 *= abs(x[i]) 36 | result = s1 + s2 37 | return result 38 | 39 | def F3(x): 40 | # xi ∈ [-100, 100] and min is 0 41 | s1 = 0 42 | for i in range(len(x)): 43 | s2 = 0 44 | for j in range(i): 45 | s2 += abs(x[i]) 46 | s1 += s2 ** 2 47 | return s1 48 | 49 | def F4(x): 50 | # xi ∈ [-100, 100] and min is 0 51 | y = [] 52 | for i in range(len(x)): 53 | y.append(abs(x[i])) 54 | return max(y) 55 | 56 | def F5(x): 57 | # xi ∈ [-30, 30] and min is 0 58 | s1 = 0 59 | for i in range(len(x) - 1): 60 | s1 += (100 * (x[i + 1] - x[i] ** 2) ** 2 + (x[i] - 1) ** 2) 61 | return s1 62 | 63 | def F6(x): 64 | # xi ∈ [-100, 100] and min is 0 65 | s1 = 0 66 | for i in range(len(x)): 67 | s1 += ((x[i] + 0.5) ** 2) 68 | return s1 69 | 70 | def F7(x): 71 | # xi ∈ [-1.28, 1.28] and min is 0 72 | s1 = 0 73 | for i in range(len(x)): 74 | s1 += (i * x[i] ** 4 + norm.rvs()) 75 | return s1 76 | 77 | # Multimodal test functions 78 | def F8(x): 79 | # xi ∈ [-500, 500] and min is -418.9829 * len(x) 80 | s1 = 0 81 | for i in range(len(x)): 82 | s1 += (-x[i] * math.sin(math.sqrt(abs(x[i])))) 83 | return s1 84 | 85 | def F9(x): 86 | # xi ∈ [-5.12, 5.12] and min is 0 87 | result = 0 88 | for i in range(len(x)): 89 | result += (x[i] ** 2 - 10 * math.cos(2 * math.pi * x[i]) + 10) 90 | return result 91 | 92 | def F10(x): 93 | # xi ∈ [-32.768, 32.768] and min is 0 94 | a = 20 95 | b = 0.2 96 | c = 2 * math.pi 97 | s1 = 0 98 | s2 = 0 99 | for i in range(len(x)): 100 | s1 += x[i] ** 2 101 | s2 += math.cos(c * x[i]) 102 | s1 = -a * math.exp(-b * math.sqrt(s1 / len(x))) 103 | s2 = -math.exp(s2 / len(x)) 104 | result = s1 + s2 + a + math.exp(1) 105 | return result 106 | 107 | def F11(x): 108 | # xi ∈ [-600, 600] and min is 0 109 | s1 = 0 110 | s2 = 1 111 | for i in range(len(x)): 112 | s1 += x[i] ** 2 113 | s2 *= math.cos(x[i] / math.sqrt(i + 1)) 114 | s1 = s1 / 4000 115 | result = s1 - s2 + 1 116 | return result 117 | 118 | # Fixed-dimension test functions # two dimension 119 | def F13(x): 120 | # x[0] and x[1] ∈ [-5, 5] and min is -1.0316 121 | x1 = x[0] 122 | x2 = x[1] 123 | result = 4 * x1 ** 2 - 2.1 * x1 ** 4 + x1 ** 6 / 3 + x1 * x2 - 4 * x2 ** 2 + 4 * x2 ** 4 124 | return result 125 | 126 | def F14(x): 127 | # x[0] and x[1] ∈ [0, 14] and min is 0 128 | x1 = x[0] 129 | x2 = x[1] 130 | s1 = math.sin(math.pi * (x1-2)) * math.sin(math.pi * (x2-2)) / (math.pi * (x2-2) * math.pi * (x1-2)) 131 | s2 = 2 + (x1-7) ** 2 + (x2-7) ** 2 132 | result = (1 - pow(abs(s1), 5)) * s2 133 | return result 134 | 135 | def F15(x): 136 | # x[0] and x[1] ∈ [-10, 10] and min is -1 137 | x1 = x[0] 138 | x2 = x[1] 139 | s1 = abs(100 - math.sqrt(x1 * x1 + x2 * x2) / math.pi) 140 | s2 = math.sin(x1) * math.sin(x2) * math.exp(s1) 141 | s3 = -math.pow((abs(s2) + 1), -0.1) 142 | return s3 143 | def F16(x): 144 | # x[0] and x[1] ∈ [-20, 20] and min is -1 145 | x1 = x[0] 146 | x2 = x[1] 147 | beta = 15 148 | m = 5 149 | s1 = math.exp(-pow(x1/beta, 2*m)-pow(x2/beta, 2*m)) 150 | s2 = 2*math.exp(-pow(x1, 2)-pow(x2, 2)) 151 | s3 = math.cos(x1)*math.cos(x2) 152 | result = (s1 - s2) * s3 * s3 153 | return result 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /WPS.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2021/12/7 14:45 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : wps.py 7 | 8 | """ 9 | There are 2 kinds of wolf pack search algorithm. 10 | The first one called wolf pack search(wps) proposed by Chenguang Yang, Xuyan Tu and Jie Chen in thier paper "Algorithm of Marriage in Honey Bees Optimization Based on the Wolf Pack Search" at 2007 International Conference on Intelligent Pervasive Computing in 2007. The wps code could ref: https://github.com/AlexanderKlanovets/swarm_algorithms/commit/78834820cadbcadb6902e3c171a2a8581255c542 11 | The second one called wolf pack algorithm proposed by 吴虎胜,张凤鸣,吴庐山 in their paper "一种新的群体智能算法-狼群算法" at Systems Engineering and Electronics in 2013. 12 | In fact, they are 2 different kinds of algorithm. WPS was shown in this file, and WPA was in wpa.py.(I meet some problems in wpa.py, so it haven't been upload.) 13 | """ 14 | 15 | import numpy as np 16 | import random 17 | import matplotlib.pyplot as plt 18 | import test_function 19 | 20 | class wps(): 21 | def __init__(self, n_dim=2, pop_size=50, max_iter=150, lb=-1e5, ub=1e5, step=0.5, func=None): 22 | # D - dimension of the search space; 23 | # N - number of wolves to generate; 24 | # step, l_near, t_max, beta - model parameters; 25 | # fitness_function - function to optimize; 26 | # w_range - range of particles' coordinates' values (from -range to range); 27 | # iter_num - maximum number of iterations. 28 | # (self, n_dim, pop_size, step, fitness_function, w_range, iter_num, l_near=0, t_max=0, beta=0): 29 | self.n_dim = n_dim 30 | self.pop = pop_size 31 | self.step = step # 影响朝最佳点靠近的速度 32 | self.func = func 33 | self.max_iter = max_iter 34 | 35 | self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim) 36 | assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' 37 | assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound' 38 | 39 | self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) 40 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles 41 | 42 | self.pbest_x = self.X.copy() # personal best location of every particle in history 43 | self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history 44 | self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles 45 | self.gbest_y = np.inf # global best y for all particles 46 | self.gbest_y_hist = [] # gbest_y of every iteration 47 | self.update_gbest() 48 | 49 | def update_pbest(self): 50 | ''' 51 | personal best 52 | :return: 53 | ''' 54 | for i in range(len(self.Y)): 55 | if self.pbest_y[i] > self.Y[i]: 56 | self.pbest_x[i] = self.X[i] 57 | self.pbest_y[i] = self.Y[i] 58 | 59 | def update_gbest(self): 60 | ''' 61 | global best 62 | :return: 63 | ''' 64 | idx_min = self.pbest_y.index(min(self.pbest_y)) 65 | if self.gbest_y > self.pbest_y[idx_min]: 66 | self.gbest_x = self.X[idx_min, :].copy() 67 | self.gbest_y = self.pbest_y[idx_min] 68 | 69 | def update(self): 70 | # 参考樽海鞘群算法 71 | # self.step = 2 * math.exp(-(4 * ((i + 1) / self.max_iter)) ** 2) 72 | for i in range(self.pop): 73 | if all(self.X[i] != self.gbest_x[0]): # self.Y[i] != self.gbest_y 74 | try: 75 | self.X[i] += self.step * (self.gbest_x[0] - self.X[i]) / np.linalg.norm(self.gbest_x[0] - self.X[i]) 76 | except: 77 | self.X[i] += self.step * (self.gbest_x - self.X[i]) / np.linalg.norm(self.gbest_x - self.X[i]) 78 | self.X = np.clip(self.X, self.lb, self.ub) 79 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # Function for fitness evaluation of new solutions 80 | 81 | def run(self): 82 | for iter in range(self.max_iter): 83 | self.update() # self.step可以选择参考樽海鞘群,随迭代次数发生改变 84 | self.update_pbest() 85 | self.update_gbest() 86 | self.gbest_y_hist.append(self.gbest_y) 87 | self.best_x, self.best_y = self.gbest_x, self.gbest_y 88 | return self.best_x, self.best_y 89 | 90 | if __name__ == '__main__': 91 | n_dim = 2 92 | lb = [-5.12 for i in range(n_dim)] 93 | ub = [5.12 for i in range(n_dim)] 94 | demo_func = test_function.f22 95 | ssa = wps(pop_size=50, n_dim=n_dim, max_iter=300, lb=lb, ub=ub, func=demo_func, step=0.5) 96 | ssa.run() 97 | print('best_x is ', ssa.gbest_x, 'best_y is', ssa.gbest_y) 98 | print(f'{demo_func(ssa.gbest_x)}\t{ssa.gbest_x}') 99 | plt.plot(ssa.gbest_y_hist) 100 | plt.show() -------------------------------------------------------------------------------- /GSA.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2022/10/19 20:32 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : GSA.py 7 | 8 | ''' 9 | Ref:https://github.com/ravexina/GSA/blob/master/GSA.py 10 | Ref:Rashedi E., Nezamabadi-Pour H., Saryazdi S. GSA: A Gravitational Search Algorithm[J]. Information Sciences, 2009, 179(13): 2232-48. 11 | ''' 12 | 13 | import numpy as np 14 | import matplotlib.pyplot as plt 15 | import math 16 | import test_function 17 | 18 | class GSA(): 19 | def __init__(self, func, n_dim=None, pop=40, max_iter=150, lb=-1e5, ub=1e5, alpha=0.1, G=0.9): 20 | self.func = func 21 | self.alpha = alpha 22 | self.G = G 23 | self.pop = pop # number of particles 24 | self.n_dim = n_dim # dimension of particles, which is the number of variables of func 25 | self.max_iter = max_iter # max iter 26 | 27 | self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim) 28 | assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' 29 | assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound' 30 | 31 | self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) 32 | v_high = (self.ub - self.lb) # 速度设置为区间长度的一半 33 | self.V = np.random.uniform(low=-v_high, high=v_high, size=(self.pop, self.n_dim)) # speed of particles 34 | self.Y = [self.func(self.X[i]) for i in range(self.pop)] # y = f(x) for all particles 35 | self.q = [1 for i in range(self.pop)] 36 | self.M = [1 for i in range(self.pop)] 37 | self.f = [[0 for j in range(self.n_dim)] for i in range(self.pop)] 38 | self.a = [[0 for j in range(self.n_dim)] for i in range(self.pop)] 39 | 40 | 41 | self.pbest_x = self.X.copy() # personal best location of every particle in history 42 | self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history 43 | self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles 44 | self.gbest_y = np.inf # global best y for all particles 45 | self.gbest_y_hist = [] # gbest_y of every iteration 46 | self.update_gbest() 47 | 48 | def cal_q_M(self): 49 | best = np.min(self.Y) 50 | worst = np.max(self.Y) 51 | self.q = (self.Y - worst) / best - worst 52 | self.M = self.q / sum(self.q) 53 | 54 | def cal_f(self): 55 | for i in range(self.pop): 56 | f = None 57 | for j in range(self.pop): 58 | if j != i: 59 | dividend = float(self.M[i] * self.M[j]) 60 | temp = self.X[i] - self.X[j] 61 | sum_temp = [k**2 for k in temp] 62 | divisor = math.sqrt(sum(sum_temp)) + np.finfo('float').eps 63 | if f is None: 64 | f = self.G * (dividend / divisor) * (self.X[j] - self.X[i]) 65 | else: 66 | f = f + self.G * (dividend / divisor) * (self.X[j] - self.X[i]) 67 | 68 | self.f[i] = np.random.uniform(0, 1) * f 69 | 70 | def update_gbest(self): 71 | idx_min = self.Y.index(min(self.Y)) 72 | if self.gbest_y > self.Y[idx_min]: 73 | self.gbest_x = self.X[idx_min, :].copy() 74 | self.gbest_y = self.Y[idx_min] 75 | 76 | def run(self): 77 | for iteration in range(self.max_iter): 78 | 79 | self.Y = [self.func(self.X[i]) for i in range(self.pop)] 80 | self.cal_q_M() 81 | self.G = self.G * np.e ** (- self.alpha * (iteration / self.max_iter)) 82 | self.cal_f() 83 | self.a = [self.f[i]/self.M[i] for i in range(self.pop)] 84 | self.V = (np.random.uniform(0, 1) * self.V) + self.a 85 | self.update_gbest() 86 | self.X = self.X + self.V 87 | self.gbest_y_hist.append(self.gbest_y) 88 | # print(iteration, self.gbest_x, self.gbest_y) 89 | self.best_x, self.best_y = self.gbest_x, self.gbest_y 90 | return self.best_x, self.best_y 91 | 92 | 93 | def demo_func(args): 94 | 95 | x, y = args[0], args[1] 96 | a = 1 97 | b = 100 98 | return (a - x) ** 2 + b * (y - x ** 2) ** 2 99 | 100 | 101 | if __name__ == '__main__': 102 | n_dim = 2 103 | lb = [0 for i in range(n_dim)] 104 | ub = [1 for i in range(n_dim)] 105 | # demo_func = test_function.fu2 106 | pop_size = 20 107 | max_iter = 100 108 | res = [] 109 | for i in range(100): 110 | pso = GSA(func=demo_func, n_dim=n_dim, pop=pop_size, max_iter=max_iter, lb=lb, ub=ub) 111 | best_x, bext_y = pso.run() 112 | print(f'{i}: {demo_func(pso.gbest_x)}\t{pso.gbest_x}') 113 | res.append(bext_y) 114 | print(sum(res)/len(res)) 115 | print(np.std(res)) 116 | # plt.plot(pso.gbest_y_hist) 117 | # 118 | # plt.show() 119 | -------------------------------------------------------------------------------- /SBO.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2021/12/3 17:36 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : SBO.py 7 | 8 | """ 9 | Ref:https://blog.csdn.net/u011835903/article/details/107857884 10 | """ 11 | 12 | import random # random Function 13 | import numpy as np # numpy operations 14 | import matplotlib.pyplot as plt 15 | import math 16 | import test_function 17 | 18 | class SBO(): 19 | def __init__(self, pop_size=50, n_dim=2, alpha=0.94, lb=-1e5, ub=1e5, max_iter=1000, func=None): 20 | self.pop = pop_size 21 | self.n_dim = n_dim 22 | self.alpha = alpha # 步长的最大阈值 23 | self.func = func 24 | self.max_iter = max_iter # max iter 25 | self.z = 0.02 # z是缩放比例因子 26 | self.r_mutate = 0.05 # 变异概率 27 | 28 | self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim) 29 | assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' 30 | assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound' 31 | 32 | self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) 33 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles 34 | 35 | self.pbest_x = self.X.copy() # personal best location of every particle in history 36 | self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history 37 | self.fit = [1 / (1 + self.Y[i]) if self.Y[i] > 0 else 1 - self.Y[i] for i in range(self.pop)] 38 | self.prob = [self.fit[i] / sum(self.fit) for i in range(self.pop)] 39 | self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles 40 | self.gbest_y = np.inf # global best y for all particles 41 | self.gbest_y_hist = [] # gbest_y of every iteration 42 | self.update_gbest() 43 | 44 | def update_pbest(self): 45 | ''' 46 | personal best 47 | :return: 48 | ''' 49 | for i in range(len(self.Y)): 50 | if self.pbest_y[i] > self.Y[i]: 51 | self.pbest_x[i] = self.X[i] 52 | self.pbest_y[i] = self.Y[i] 53 | 54 | def update_gbest(self): 55 | ''' 56 | global best 57 | :return: 58 | ''' 59 | idx_min = self.pbest_y.index(min(self.pbest_y)) 60 | if self.gbest_y > self.pbest_y[idx_min]: 61 | self.gbest_x = self.X[idx_min, :].copy() 62 | self.gbest_y = self.pbest_y[idx_min] 63 | 64 | def cal_prob(self): 65 | self.fit = [1 / (1 + self.Y[i]) if self.Y[i] > 0 else 1 - self.Y[i] for i in range(self.pop)] 66 | self.prob = [self.fit[i] / sum(self.fit) for i in range(self.pop)] 67 | 68 | def update(self, iter_num): 69 | idx_min = self.Y.index(min(self.Y)) 70 | for i in range(self.pop): 71 | # roulette wheel 72 | for k in range(self.n_dim): 73 | select_list = [] 74 | while len(select_list) < 1: 75 | select_list = [] 76 | r = np.random.rand(1) 77 | for kk in range(len(self.prob)): 78 | if self.prob[kk] > (r[0]): 79 | select_list.append(kk) 80 | j = random.choice(select_list) 81 | lemta = self.alpha / (1 + self.prob[j]) 82 | try: 83 | self.X[i, k] += lemta * 0.5 * (self.X[j, k] + self.gbest_x[0][k] - 2 * self.X[i, k]) 84 | except: 85 | self.X[i, k] += lemta * 0.5 * (self.X[j, k] + self.gbest_x[k] - 2 * self.X[i, k]) 86 | 87 | # 变异 88 | if np.random.rand(1) < self.r_mutate and i != idx_min: 89 | for j in range(self.n_dim): 90 | # 正态分布 Satin bowerbird optimizer: A new optimization algorithm to optimize 91 | # ANFIS for software development effort estimation.pdf 92 | self.X[i][j] += self.z * np.random.normal() * (self.ub[j] - self.lb[j]) 93 | self.X = np.clip(self.X, self.lb, self.ub) 94 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] 95 | 96 | # def mutate(self): 97 | # # 没有用上这个函数 98 | # idx_min = self.Y.index(min(self.Y)) 99 | # for i in range(self.pop): 100 | # if np.random.rand(1)[0] < self.r_mutate and i != idx_min: 101 | # for j in range(self.n_dim): 102 | # self.X[i][j] += self.z * np.random.normal() * (self.ub[j] - self.lb[j]) 103 | # self.X = np.clip(self.X, self.lb, self.ub) 104 | # self.Y = [self.func(self.X[i]) for i in range(len(self.X))] 105 | 106 | def run(self): 107 | for i in range(self.max_iter): 108 | print(i) 109 | self.update(i) 110 | self.cal_prob() 111 | self.update_pbest() 112 | self.update_gbest() 113 | self.gbest_y_hist.append(self.gbest_y) 114 | self.best_x, self.best_y = self.gbest_x, self.gbest_y 115 | return self.best_x, self.best_y 116 | 117 | if __name__ == '__main__': 118 | # 寻优效果不错,但是计算时间较长,有一部分原因是我频繁整体计算适应度值 119 | n_dim = 30 120 | lb = [-100 for i in range(n_dim)] 121 | ub = [100 for i in range(n_dim)] 122 | demo_func = test_function.fu5 123 | pop_size = 100 124 | max_iter = 100 125 | sbo = SBO(n_dim=n_dim, pop_size=pop_size, max_iter=max_iter, lb=lb, ub=ub, func=demo_func) 126 | best_x, bext_y = sbo.run() 127 | print(f'{demo_func(sbo.gbest_x)}\t{sbo.gbest_x}') 128 | plt.plot(sbo.gbest_y_hist) 129 | plt.show() 130 | 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swarm-intelligence-optimization-algorithm 2 | 3 | [![PyPI](https://img.shields.io/pypi/v/swarm-algorithm)](https://pypi.org/project/swarm-algorithm/) 4 | [![License](https://img.shields.io/pypi/l/swarm-algorithm.svg)](https://github.com/LucXiong/Swarm-intelligence-optimization-algorithm/blob/master/LICENSE) 5 | ![Python](https://img.shields.io/badge/python->=3.5-green.svg) 6 | [![fork](https://img.shields.io/github/forks/LucXiong/Swarm-intelligence-optimization-algorithm?style=social)](https://github.com/LucXiong/Swarm-intelligence-optimization-algorithm/fork) 7 | [![star](https://img.shields.io/github/stars/LucXiong/Swarm-intelligence-optimization-algorithm?style=social)](https://github.com/LucXiong/Swarm-intelligence-optimization-algorithm/star) 8 | [![Downloads](https://pepy.tech/badge/swarm-algorithm)](https://pepy.tech/project/swarm-algorithm) 9 | [![Discussions](https://img.shields.io/badge/discussions-green.svg)](https://github.com/LucXiong/Swarm-intelligence-optimization-algorithm/discussions) 10 | 11 | 种群算法复现,由于已由[大佬](https://github.com/guofei9987/scikit-opt)开发了种群算法的第三方库,包括退火算法(SA)、粒子群算法(PSO)、人工免疫算法(IA)、遗传算法(GA)、差分进化算法(DE)、人工鱼群算法(AFSA)、蚁群算法(ACA),标*1的表示从中copy过来的,但是删除了其中部分带有约束的部分,所以如果需要带有约束的原始算法可以去[大佬](https://github.com/guofei9987/scikit-opt)开发的种群算法的第三方库。另一个已有的[第三方种群算法库](https://github.com/HaaLeo/swarmlib)包括布谷鸟搜索算法(CS)、萤火虫算法(FA2009)、灰狼算法(GWO)、鲸鱼算法(WOA)、人工蜂群算法(ABC),标*2的表示从中copy过来的。如有冒犯或者侵权,可联系删除。此仓库新增了二者没有一些种群算法。 12 | 可安装此第三方库调用此仓库已复现种群算法,若有问题,可随时联系。 13 | 14 | ```python 15 | pip install swarm-algorithm 16 | ``` 17 | 18 | 遗传算法(DA)、差分进化算法(DE)、粒子群算法(PSO*11995)、狼群搜索算法(WPS2007, WPA2013)、引力搜索算法(GSA2009)、烟花算法(FA2010)、乌鸦搜索(CSA2016)、正余弦优化算法(CSA2016)、樽海鞘群算法(SSA2017)、缎蓝园丁鸟优化算法(SBO2017)、麻雀搜索算法(SSA2020) 19 | ## 1995 Particle Swarm Optimization(PSO)*1 20 | Kennedy J, Eberhart R. Particle swarm optimization[C]// [Particle swarm optimization](https://ieeexplore.ieee.org/abstract/document/488968). Proceedings of ICNN'95 - International Conference on Neural Networks, 27 Nov.-1 Dec. 1995.4: 1942-8 vol.4. 21 | ```python 22 | import swarm-algorithm 23 | pso = swarm-algorithm.PSO(func, n_dim=20, pop=40, max_iter=150, lb=-1e5, ub=1e5, w=0.8, c1=0.5, c2=0.5) 24 | # n_dim : 变量维数 25 | # pop : 种群数量 26 | # max_iter : 最大迭代次数 27 | # lb : 变量下界,维数为n_dim的列表 28 | # ub : 变量上届,维数为n_dim的列表 29 | # w、c1、c2 : 粒子更新规则的相关参数 30 | n_dim = 30 31 | lb = [-100 for i in range(n_dim)] 32 | ub = [100 for i in range(n_dim)] 33 | demo_func = test_function.fu2 34 | pop_size = 100 35 | max_iter = 1000 36 | pso = PSO(func=demo_func, n_dim=n_dim, pop=100, max_iter=1000, lb=lb, ub=ub, w=0.8, c1=0.5, c2=0.5) 37 | best_x, bext_y = pso.run() 38 | print(f'{demo_func(pso.gbest_x)}\t{pso.gbest_x}') 39 | ``` 40 | ## 2007 Wolf Pack Search(WPS) 41 | Yang C, Tu X, Chen J. [Algorithm of Marriage in Honey Bees Optimization Based on the Wolf Pack Search](https://www.computer.org/csdl/proceedings-article/ipc/2007/30060462/12OmNzC5T5U), Jeju Island, Korea, 2007: 462-7. 42 | ## 2009 Gravitational Search Algorithm(GSA) 43 | Rashedi E., Nezamabadi-Pour H., [Saryazdi S. GSA: A Gravitational Search Algorithm](https://www.sciencedirect.com/science/article/pii/S0020025509001200)[J]. Information Sciences, 2009, 179(13): 2232-48. 44 | ## 2010 Fireworks Algorithm(FA2010) 45 | Tan Y, Zhu Y. [Fireworks Algorithm for Optimization](https://www.researchgate.net/publication/220704568_Fireworks_Algorithm_for_Optimization#:~:text=Inspired%20by%20observing%20fireworks%20explosion%2C%20a%20novel%20swarm,keeping%20diversity%20of%20sparks%20are%20also%20well%20designed.)[M]. // Lecture Notes in Computer Science. City: Springer Berlin Heidelberg, 2010: 355-64[2021-12-08T08:42:21]. 46 | ## 2013 Wolf Pack Algorithm(WPA) 47 | 吴虎胜, 张凤鸣, 吴庐山. [一种新的群体智能算法——狼群算法](https://oss.wanfangdata.com.cn/www/%E4%B8%80%E7%A7%8D%E6%96%B0%E7%9A%84%E7%BE%A4%E4%BD%93%E6%99%BA%E8%83%BD%E7%AE%97%E6%B3%95%E2%80%94%E2%80%94%E7%8B%BC%E7%BE%A4%E7%AE%97%E6%B3%95.ashx?isread=true&type=perio&resourceId=xtgcydzjs201311033&transaction=%7B%22id%22%3Anull%2C%22transferOutAccountsStatus%22%3Anull%2C%22transaction%22%3A%7B%22id%22%3A%221478253592753254400%22%2C%22status%22%3A1%2C%22createDateTime%22%3Anull%2C%22payDateTime%22%3A1641278095793%2C%22authToken%22%3A%22TGT-21025086-NNOedndoqocfHmrAEEpa2NPFM54hlRyq9Iydysp3Vdrm52ZAb0-my.wanfangdata.com.cn%22%2C%22user%22%3A%7B%22accountType%22%3A%22Group%22%2C%22key%22%3A%22shjtdxip%22%7D%2C%22transferIn%22%3A%7B%22accountType%22%3A%22Income%22%2C%22key%22%3A%22PeriodicalFulltext%22%7D%2C%22transferOut%22%3A%7B%22GTimeLimit.shjtdxip%22%3A3.0%7D%2C%22turnover%22%3A3.0%2C%22orderTurnover%22%3A3.0%2C%22productDetail%22%3A%22perio_xtgcydzjs201311033%22%2C%22productTitle%22%3Anull%2C%22userIP%22%3A%22202.120.11.15%22%2C%22organName%22%3Anull%2C%22memo%22%3Anull%2C%22orderUser%22%3A%22shjtdxip%22%2C%22orderChannel%22%3A%22pc%22%2C%22payTag%22%3A%22%22%2C%22webTransactionRequest%22%3Anull%2C%22signature%22%3A%22DDZm%2FVXekyWdH42BgPDeLSdnJXD5YPlUmPP6RP2%2B5eU5k97eueMNcfB2qDS7gmRqjIAbT8ocLpCg%5CnFfEPHohFBJ9J%2BFzviaDCPBw8d6hI01pf4vPVSg9Dd2I4TakD%2FYViqh584dU9xvUJbBOxU8%2BaFsyF%5CnDfCN60TgqVGcQgxpefQ%3D%22%2C%22delete%22%3Afalse%7D%2C%22isCache%22%3Afalse%7D)[J]. 系统工程与电子技术, 2013, 35(11): 2430-8. 48 | 49 | [New swarm intelligence algorithm--wolf pack algorithm](https://www.researchgate.net/publication/264928582_New_swarm_intelligence_algorithm-wolf_pack_algorithm) 50 | ## 2016 Crow Search Algorithm(CSA) 51 | Askarzadeh A. [A novel metaheuristic method for solving constrained engineering optimization problems: Crow search algorithm](https://www.sciencedirect.com/science/article/pii/S0045794916300475)[J]. Computers & Structures, 2016, 169: 1-12. 52 | ## 2017 Salp Swarm Algorithm(SSA) 53 | Mirjalili S, Gandomi A H, Mirjalili S Z, et al. [Salp Swarm Algorithm: A bio-inspired optimizer for engineering design problems](https://www.sciencedirect.com/science/article/pii/S0965997816307736)[J]. Advances in Engineering Software, 2017, 114: 163-91. 54 | ## 2017 Sine Cosine Algorithm(SCA) 55 | Mirjalili S. [SCA: A Sine Cosine Algorithm for solving optimization problems](https://www.sciencedirect.com/science/article/pii/S0950705115005043)[J]. Knowledge-Based Systems, 2016, 96: 120-33. 56 | ## 2017 Satin Bowerbird Optimizer(SBO) 57 | Samareh Moosavi S H, Khatibi Bardsiri V. [Satin bowerbird optimizer: A new optimization algorithm to optimize ANFIS for software development effort estimation](https://www.sciencedirect.com/science/article/pii/S095219761730006)[J]. Engineering Applications of Artificial Intelligence, 2017, 60: 1-15. 58 | ## 2020 Sparrow Search Algorithm(SSA) 59 | Xue J, Shen B. [A novel swarm intelligence optimization approach: sparrow search algorithm](https://www.tandfonline.com/doi/pdf/10.1080/21642583.2019.1708830)[J]. Systems Science & Control Engineering, 2020, 8(1): 22-34. 60 | 61 | -------------------------------------------------------------------------------- /FA.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2021/12/15 15:02 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : FA.py 7 | 8 | """ 9 | Ref:https://github.com/GoodLittleStar/Fireworks/blob/master/FireWork.py 10 | Ref:Tan Y, Zhu Y. Fireworks Algorithm for Optimization[M]. 11 | Lecture Notes in Computer Science. City: Springer Berlin Heidelberg, 2010: 355-64[2021-12-08T08:42:21]. 12 | """ 13 | 14 | import random # random Function 15 | import numpy as np # numpy operations 16 | import copy 17 | import matplotlib.pyplot as plt 18 | import math 19 | import test_function 20 | 21 | class FA(): 22 | def __init__(self, pop_size=50, n_dim=2, m=50, a=0.04, b=0.8, A=40, lb=-1e5, ub=1e5, max_iter=1000, func=None): 23 | 24 | self.a = a 25 | self.b = b 26 | self.m = m 27 | self.A = A 28 | self.pop = pop_size 29 | self.dim = n_dim 30 | self.func = func 31 | self.max_iter = max_iter # max iter 32 | self.epsino = 1e-6 33 | self.mutate = 0.1 34 | 35 | self.lb, self.ub = np.array(lb) * np.ones(self.dim), np.array(ub) * np.ones(self.dim) 36 | assert self.dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' 37 | assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound' 38 | 39 | self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.dim)) 40 | self.X = self.X.tolist() 41 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles 42 | 43 | self.bestindex = self.Y.index(min(self.Y)) 44 | self.gbest_x = self.X[self.bestindex] 45 | self.gbest_y = min(self.Y) # global best y for all particles 46 | self.gbest_y_hist = [self.gbest_y] # gbest_y of every iteration 47 | # self.update_gbest() 48 | 49 | 50 | def CalculateSi(self): 51 | self.MaxFitness = max(self.Y) 52 | temp = 0. 53 | self.Si = [] 54 | for i in range(0, self.pop): 55 | temp = temp + self.MaxFitness - self.Y[i] 56 | for i in range(0, self.pop): 57 | self.Si.append(self.m * (self.MaxFitness - self.Y[i] + self.epsino) / (temp + self.epsino)) 58 | if self.Si[-1] < self.a * self.m: 59 | self.Si[-1] = round(self.a * self.m) 60 | elif self.Si[-1] > self.b * self.m: 61 | self.Si[-1] = round(self.b * self.m) 62 | else: 63 | self.Si[-1] = round(self.Si[-1]) 64 | 65 | def CalculateExpo(self): 66 | self.MinFitness = min(self.Y) 67 | temp = 0. 68 | self.Ai = [] 69 | for i in range(self.pop): 70 | temp = temp + self.Y[i] - self.MinFitness 71 | for i in range(self.pop): 72 | self.Ai.append(self.A * (self.Y[i]- self.MinFitness + self.epsino) / (temp + self.epsino)) 73 | 74 | def Explosion(self): 75 | for k in range(0, self.pop): 76 | for i in range(self.Si[k]): 77 | spark = copy.deepcopy(self.X[k]) 78 | z = round(self.dim * random.uniform(0, 1)) 79 | dim_list = range(self.dim) 80 | rand_z = random.sample(dim_list, z) 81 | h = self.Ai[k] * random.uniform(-1, 1) 82 | for j in rand_z: 83 | spark[j] += h 84 | if spark[j] < self.lb[j] or spark[j] > self.ub[j]: 85 | spark[j] = self.lb[j] + abs(spark[j]) % (self.ub[j] - self.lb[j]) 86 | self.X.append(spark) 87 | self.Y.append(self.func(spark)) 88 | if(len(self.X) > 5 * self.pop): 89 | break 90 | 91 | def Mutation(self): 92 | currentsize = len(self.X) 93 | for k in range(round(self.mutate * currentsize)): 94 | randindex = random.randint(0, currentsize - 1) 95 | spark = copy.deepcopy(self.X[randindex]) 96 | # print(spark) 97 | # print(randindex) 98 | z = round(self.dim * random.uniform(0, 1)) 99 | dim_list = range(self.dim) 100 | rand_z = random.sample(dim_list, z) 101 | g = random.gauss(1, 1) 102 | for j in rand_z: 103 | spark[j] *= g 104 | if spark[j] < self.lb[j] or spark[j] > self.ub[j]: 105 | spark[j] = self.lb[j] + abs(spark[j]) % (self.ub[j] - self.lb[j]) 106 | self.X.append(spark) 107 | self.Y.append(self.func(spark)) 108 | if (len(self.X) > 10 * self.pop): 109 | break 110 | 111 | def Selection(self): 112 | newpop=[] 113 | newpop.append(self.gbest_x) 114 | self.Ri = [] 115 | for i in range(len(self.X)): 116 | dis=0. 117 | for j in range(len(self.X)): 118 | for k in range(self.dim): 119 | dis+= (self.X[i][k]-self.X[j][k])**2 120 | self.Ri.append(math.sqrt(dis)) 121 | sr = sum(self.Ri) 122 | px = [self.Ri[i]/sr for i in range(len(self.Ri))] 123 | for i in range(self.pop-1): 124 | rr=random.uniform(0,1) 125 | index=0 126 | for j in range(self.pop): 127 | if j==0 and rr=px[j] and rr self.Y[bestindex]: 147 | self.gbest_y_hist.append(self.Y[bestindex]) 148 | self.gbest_x = self.X[bestindex] 149 | else: 150 | self.gbest_y_hist.append(self.gbest_y_hist[-1]) 151 | self.Selection() 152 | # print(self.gbest_y_hist[-1]) 153 | return self.gbest_x, self.gbest_y_hist[-1] 154 | 155 | if __name__ == '__main__': 156 | n_dim = 3 157 | lb = [-100 for i in range(n_dim)] 158 | ub = [100 for i in range(n_dim)] 159 | demo_func = test_function.fm2 160 | pop_size = 10 161 | max_iter = 20 162 | fa = FA(n_dim=n_dim, pop_size=pop_size, max_iter=max_iter, lb=lb, ub=ub, func=demo_func) 163 | best_x, bext_y = fa.run() 164 | print(f'{demo_func(fa.gbest_x)}\t{fa.gbest_x}') 165 | plt.plot(fa.gbest_y_hist) 166 | plt.show() 167 | -------------------------------------------------------------------------------- /SSA2020.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2021/12/2 11:10 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : SSA.py 7 | 8 | """ 9 | Ref:https://github.com/changliang5811/SSA_python 10 | Ref:https://www.tandfonline.com/doi/full/10.1080/21642583.2019.1708830 11 | Ref:A novel swarm intelligence optimization approach: sparrow search algorithm.pdf 12 | """ 13 | 14 | import numpy as np 15 | import matplotlib.pyplot as plt 16 | import math 17 | from scipy.stats import norm 18 | import random 19 | import test_function 20 | 21 | class SSA(): 22 | def __init__(self, func, n_dim=None, pop_size=20, max_iter=50, lb=-512, ub=512, verbose=False): 23 | self.func = func 24 | self.n_dim = n_dim # dimension of particles, which is the number of variables of func 25 | self.pop = pop_size # number of particles 26 | P_percent = 0.2 # # 生产者的人口规模占总人口规模的20% 27 | D_percent = 0.1 # 预警者的人口规模占总人口规模的10% 28 | self.pNum = round(self.pop * P_percent) # 生产者的人口规模占总人口规模的20% 29 | self.warn = round(self.pop * D_percent) # 预警者的人口规模占总人口规模的10% 30 | 31 | self.max_iter = max_iter # max iter 32 | self.verbose = verbose # print the result of each iter or not 33 | 34 | self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim) 35 | assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' 36 | assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound' 37 | 38 | self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) 39 | 40 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles 41 | self.pbest_x = self.X.copy() # personal best location of every particle in history 42 | self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history 43 | self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles 44 | self.gbest_y = np.inf # global best y for all particles 45 | self.gbest_y_hist = [] # gbest_y of every iteration 46 | self.update_pbest() 47 | self.update_gbest() 48 | # 49 | # record verbose values 50 | self.record_mode = False 51 | self.record_value = {'X': [], 'V': [], 'Y': []} 52 | self.best_x, self.best_y = self.gbest_x, self.gbest_y # history reasons, will be deprecated 53 | self.idx_max = 0 54 | self.x_max = self.X[self.idx_max, :] 55 | self.y_max = self.Y[self.idx_max] 56 | 57 | def cal_y(self, start, end): 58 | for i in range(start, end): 59 | self.Y[i] = self.func(self.X[i]) 60 | 61 | def update_pbest(self): 62 | ''' 63 | personal best 64 | :return: 65 | ''' 66 | for i in range(len(self.Y)): 67 | if self.pbest_y[i] > self.Y[i]: 68 | self.pbest_x[i] = self.X[i] 69 | self.pbest_y[i] = self.Y[i] 70 | 71 | def update_gbest(self): 72 | ''' 73 | global best 74 | :return: 75 | ''' 76 | idx_min = self.pbest_y.index(min(self.pbest_y)) 77 | if self.gbest_y > self.pbest_y[idx_min]: 78 | self.gbest_x = self.X[idx_min, :].copy() 79 | self.gbest_y = self.pbest_y[idx_min] 80 | 81 | def find_worst(self): 82 | self.idx_max = self.Y.index(max(self.Y)) 83 | self.x_max = self.X[self.idx_max, :] 84 | self.y_max = self.Y[self.idx_max] 85 | 86 | def update_finder(self, iter_num): 87 | self.idx = sorted(enumerate(self.Y), key=lambda x: x[1]) 88 | self.idx = [self.idx[i][0] for i in range(len(self.idx))] 89 | # 这一部位为发现者(探索者)的位置更新 90 | for i in range(self.pNum): 91 | r2 = np.random.rand(1) # 预警值 92 | if r2 < 0.8: # 预警值较小,说明没有捕食者出现 93 | r1 = np.random.rand(1) 94 | self.X[self.idx[i], :] = self.X[self.idx[i], :] * np.exp( 95 | -(iter_num) / (r1 * self.max_iter)) # 对自变量做一个随机变换 96 | else: 97 | Q = np.random.normal(loc=0, scale=1.0, 98 | size=1) # np.random.rand(1) # 也可以替换成 np.random.normal(loc=0, scale=1.0, size=1) 99 | self.X[self.idx[i], :] = self.X[self.idx[i], :] + Q * np.ones( 100 | (1, self.n_dim)) # Q是服从正态分布的随机数。L表示一个1×d的矩阵 101 | self.X = np.clip(self.X, self.lb, self.ub) # 对超过边界的变量进行去除 102 | self.cal_y(0, self.pNum) 103 | 104 | def update_follower(self): 105 | # 这一部位为加入者(追随者)的位置更新 106 | for ii in range(self.pop - self.pNum): 107 | i = ii + self.pNum 108 | A = np.floor(np.random.rand(1, self.n_dim) * 2) * 2 - 1 109 | best_idx = self.Y[0:self.pNum].index(min(self.Y[0:self.pNum])) 110 | bestXX = self.X[best_idx, :] 111 | if i > self.pop/2: 112 | Q = np.random.rand(1) 113 | self.X[self.idx[i],:] = Q*np.exp((self.x_max-self.X[self.idx[i],:])/np.square(i)) 114 | else: 115 | self.X[self.idx[i],:] = bestXX+np.dot(np.abs(self.X[self.idx[i],:]-bestXX),1/(A.T*np.dot(A,A.T)))*np.ones((1, self.n_dim)) 116 | self.X = np.clip(self.X, self.lb, self.ub) # 对超过边界的变量进行去除 117 | self.cal_y(self.pNum, self.pop) 118 | 119 | def detect(self): 120 | arrc = np.arange(self.pop) 121 | c = np.random.permutation(arrc) # 随机排列序列 122 | b = [self.idx[i] for i in c[0: self.warn]] 123 | e = 10e-10 124 | for j in range(len(b)): 125 | if self.Y[b[j]] > self.gbest_y: 126 | self.X[b[j], :] = self.gbest_x + norm.rvs(size=self.n_dim) * np.abs(self.X[b[j], :] - self.gbest_x) 127 | else: 128 | self.X[b[j], :] = self.X[b[j], :]+(2*np.random.rand(1)-1)*np.abs(self.X[b[j], :]-self.x_max)/(self.func(self.X[b[j]])-self.y_max+e) 129 | self.X = np.clip(self.X, self.lb, self.ub) 130 | self.Y[b[j]] = self.func(self.X[b[j]]) 131 | 132 | def run(self, max_iter=None): 133 | self.max_iter = max_iter or self.max_iter 134 | for iter_num in range(self.max_iter): 135 | self.update_finder(iter_num) # 更新发现者位置 136 | self.find_worst() # 取出最大的适应度值和最差适应度的X 137 | self.update_follower() # 更新跟随着位置 138 | self.update_pbest() 139 | self.update_gbest() 140 | self.find_worst() # 取出最大的适应度值和最差适应度的X 141 | self.detect() 142 | self.update_pbest() 143 | self.update_gbest() 144 | self.gbest_y_hist.append(self.gbest_y) 145 | return self.best_x, self.best_y 146 | 147 | if __name__ == '__main__': 148 | n_dim = 30 149 | lb = [-100 for i in range(n_dim)] 150 | ub = [100 for i in range(n_dim)] 151 | demo_func = test_function.fu5 152 | pop_size = 100 153 | max_iter = 100 154 | ssa = SSA(demo_func, n_dim=n_dim, pop_size=pop_size, max_iter=max_iter, lb=lb, ub=ub) 155 | ssa.run() 156 | print('best_x is ', ssa.gbest_x, 'best_y is', ssa.gbest_y) 157 | # print(f'{demo_func(ssa.gbest_x)}\t{ssa.gbest_x}') 158 | plt.plot(ssa.gbest_y_hist) 159 | plt.show() 160 | -------------------------------------------------------------------------------- /test_function.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2021/12/6 10:44 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : test_func.py 7 | 8 | """ 9 | https://blog.csdn.net/miscclp/article/details/38102831 10 | """ 11 | import math 12 | import random 13 | from scipy.stats import norm 14 | # Unimodal test functions 15 | def fu1(x): 16 | # Sphere function 17 | # min is 0 at [0 for i in range(len(x)] 18 | s1 = 0 19 | for i in range(len(x)): 20 | s1 += (x[i] ** 2) 21 | return s1 22 | 23 | def fu2(x): 24 | ''' 25 | min is 0 at [0 for i in range(len(x)] 26 | :param x: xi ∈ [-10, 10] 27 | :return: 28 | ''' 29 | 30 | s1 = 0 31 | s2 = 1 32 | for i in range(len(x)): 33 | s1 += abs(x[i]) 34 | s2 *= abs(x[i]) 35 | result = s1 + s2 36 | return result 37 | 38 | def fu3(x): 39 | # min is 0 at [0 for i in range(len(x)] 40 | s1 = 0 41 | for i in range(len(x)): 42 | s2 = 0 43 | for j in range(i): 44 | s2 += abs(x[i]) 45 | s1 += s2 ** 2 46 | result = s1 47 | return result 48 | 49 | def fu4(x): 50 | # min is 0 at [0 for i in range(len(x)] 51 | y = [] 52 | for i in range(len(x)): 53 | y.append(abs(x[i])) 54 | return max(y) 55 | 56 | def fu5(x): 57 | ''' 58 | min is 0 at [-0.5 for i in range(len(x)] 59 | :param x: 60 | :return: 61 | ''' 62 | s1 = 0 63 | for i in range(len(x)): 64 | s1 += (abs(x[i] + 0.5) ** 2) 65 | result = s1 66 | return result 67 | 68 | def fu6(x): 69 | ''' Rosenbrock function 70 | min is 0 at [1 for i in range(len(x)] 71 | :param x: 72 | :return: 73 | ''' 74 | s1 = 0 75 | for i in range(len(x) - 1): 76 | s1 += (100 * (x[i+1] - x[i] ** 2) ** 2 + (x[i] - 1) ** 2) 77 | result = s1 78 | return result 79 | 80 | def fu7(x): 81 | s1 = 0 82 | for i in range(len(x)): 83 | s1 += (i * x[i] ** 4 + norm.rvs()) 84 | result = s1 85 | return result 86 | 87 | # Multimodal test functions 88 | def fm1(x): # Eggholder Function 89 | ''' 90 | min is 0 at [0 for i in range(len(x)] 91 | :param x: xi ∈ [-5.12, 5.12] 92 | :return: 93 | ''' 94 | result = 0 95 | for i in range(len(x)): 96 | result += (x[i] ** 2 - 10 * math.cos(2 * math.pi * x[i]) + 10) 97 | return result 98 | 99 | def fm2(x): 100 | ''' 101 | GRIEWANK FUNCTION:http://www.sfu.ca/~ssurjano/griewank.html 102 | :param x:-600,600 103 | :return: 104 | ''' 105 | s1 = 0 106 | s2 = 1 107 | for i in range(len(x)): 108 | s1 += x[i] ** 2 109 | s2 *= math.cos(x[i] / math.sqrt(i + 1)) 110 | s1 = s1 / 4000 111 | result = s1 - s2 + 1 112 | return result 113 | 114 | def fm3(x): 115 | # min is −418.9829 * len(x) 116 | # x: -500, 500 117 | s1 = 0 118 | for i in range(len(x)): 119 | s1 += -x[i] * math.sin(math.sqrt(abs(x[i]))) 120 | result = s1 121 | return result 122 | 123 | def fm4(x): 124 | ''' 125 | ACKLEY FUNCTION:http://www.sfu.ca/~ssurjano/ackley.html 126 | :param x:xi ∈ [-32.768, 32.768] 127 | :return: 128 | ''' 129 | a = 20 130 | b = 0.2 131 | c = 2 * math.pi 132 | s1 = 0 133 | s2 = 0 134 | for i in range(len(x)): 135 | s1 += x[i] ** 2 136 | s2 += math.cos(c * x[i]) 137 | s1 = -a * math.exp(-b * math.sqrt(s1 / len(x))) 138 | s2 = -math.exp(s2 / len(x)) 139 | result = s1 + s2 + a + math.exp(1) 140 | return result 141 | 142 | def fm5(x): 143 | # x: -50, 50 144 | def y(xi): 145 | y = 1 + (xi + 1) / 4 146 | return y 147 | 148 | def u(xi): 149 | a = 10 150 | k = 100 151 | m = 4 152 | if xi > a: 153 | u = k * pow((xi -a), m) 154 | elif xi < -a: 155 | u = k * pow((-xi - a), m) 156 | else: 157 | u = 0 158 | return u 159 | 160 | s1 = 10 * math.sin(math.pi * y(x[0])) ** 2 + (y(x[-1]) - 1) ** 2 161 | # s1 = 10 * math.sin(math.pi * y(x[0])) + (y(x[-1]) - 1) ** 2 162 | # 在已有的算法文章中使用的关于fm5的测试函数s1 = 10 * math.sin(math.pi * y(x[0])) + (y(x[-1]) - 1) ** 2 163 | # Xue J, Shen B. A novel swarm intelligence optimization approach: sparrow search algorithm[J]. 164 | # Systems Science & Control Engineering, 2020, 8(1): 22-34. 中的F12 165 | #Mirjalili S, Lewis A. The Whale Optimization Algorithm[J]. Advances in Engineering Software, 166 | # 2016, 95: 51-67. 中的F12 167 | # 但是在这种情况下,该测试函数的理论最小值显然不是0;因此怀疑文章关于此测试函数的描述出现了问题 168 | # 比如当x[0]=1,x[i]=-1(i!=0)时,此时的F12<0 169 | for i in range(len(x)-1): 170 | s1 += ((y(x[i]) - 1) ** 2 * (1 + 10 * math.sin(math.pi * y(x[i+1])) ** 2)) 171 | s2 = 0 172 | for i in range(len(x)): 173 | s2 += u(x[i]) 174 | result = s1 * math.pi / len(x) + s2 175 | return result 176 | 177 | # . Fixed-dimension test functions 178 | # two dimension 179 | def f21(x): 180 | ''' 181 | BUKIN FUNCTION N. 6:http://www.sfu.ca/~ssurjano/bukin6.html 182 | :param x: x1 ∈ [-15, -5], x2 ∈ [-3, 3]. 183 | :return: 184 | ''' 185 | s1 = 100 * math.sqrt(abs(x[1] - 0.01 * x[0] ** 2)) 186 | s2 = 0.01 * abs(x[0] + 10) 187 | result = s1 + s2 188 | return result 189 | 190 | def f22(x): 191 | # min is -1.0316 192 | x1 = x[0] 193 | x2 = x[1] 194 | result = 4 * x1 ** 2 - 2.1 * x1 ** 4 + x1 ** 6 /3 + x1 * x2 - 4 * x2 ** 2 + 4 * x2 ** 4 195 | return result 196 | 197 | def f23(x): 198 | # Eggholder function: 199 | # xi ∈ [-512, 512] 200 | # min is f(512, 404.2319) =-959.6407 201 | x1 = x[0] 202 | x2 = x[1] 203 | result = -(x2 + 47) * math.sin(math.sqrt(math.fabs(x1 + x2/2 + 47))) - x1 * math.sin(math.sqrt(math.fabs(x1 - x2 - 47))) 204 | return result 205 | 206 | def f24(x): 207 | # Ackley's function 208 | # xi ∈ [-5, 5] 209 | # min is f(0, 0) = 0 210 | x1 = x[0] 211 | x2 = x[1] 212 | s1 = -20 * math.exp(-math.sqrt((x1 ** 2 + x2 ** 2)/50)) 213 | s2 = math.exp(0.5 * math.cos(2 * math.pi * x1) + math.cos(2 * math.pi * x2)) 214 | result = s1 - s2 + 20 + math.e 215 | return result 216 | 217 | def f25(x): 218 | # Beale 's function 219 | # xi ∈ [-4.5, 4.5] 220 | # min is f(3, 0.5) = 0 221 | x1 = x[0] 222 | x2 = x[1] 223 | s1 = (1.5 - x1 + x1 * x2) ** 2 224 | s2 = (2.25 - x1 + x1 * x2 * x2) ** 2 225 | s3 = (2.625 - x1 + x1 * x2 * x2 * x2) ** 2 226 | result = s1 + s2 + s3 227 | return result 228 | 229 | def f26(x): 230 | # Lévi function N.13 231 | # xi ∈ [-10, 10] 232 | # min is f(1, 1) = 0 233 | x1 = x[0] 234 | x2 = x[1] 235 | s1 = (math.sin(3 * math.pi * x1)) ** 2 236 | s2 = (x1 - 1) * (x1 - 1) * (1 + (math.sin(3 * math.pi * x2)) ** 2) 237 | s3 = (x2 - 1) * (x2 - 1) * (1 + (math.sin(3 * math.pi * x2)) ** 2) 238 | result = s1 + s2 + s3 239 | return result 240 | 241 | def f27(x): 242 | # Cross-in-tray function: 243 | # xi ∈ [-10, 10] 244 | # min is f(±1.34941, ±1.34941) = -2.06261 245 | x1 = x[0] 246 | x2 = x[1] 247 | s1 = abs(100 - math.sqrt(x1 * x1 + x2 * x2) / math.pi) 248 | s2 = math.sin(x1) * math.sin(x2) * math.exp(s1) 249 | s3 = -0.0001 * math.pow((abs(s2) + 1), 0.1) 250 | result = s3 251 | return result 252 | 253 | if __name__ == '__main__': 254 | pass -------------------------------------------------------------------------------- /WPA.py: -------------------------------------------------------------------------------- 1 | # !usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Time : 2021/12/7 14:06 4 | # @Author : LucXiong 5 | # @Project : Model 6 | # @File : wpa.py 7 | 8 | """ 9 | There are 2 kinds of wolf pack search algorithm. 10 | The first one called wolf pack search(wps) proposed by Chenguang Yang, Xuyan Tu and Jie Chen in thier paper "Algorithm of Marriage in Honey Bees Optimization Based on the Wolf Pack Search" at 2007 International Conference on Intelligent Pervasive Computing in 2007. The wps code could ref: https://github.com/AlexanderKlanovets/swarm_algorithms/commit/78834820cadbcadb6902e3c171a2a8581255c542 11 | The second one called wolf pack algorithm proposed by 吴虎胜,张凤鸣,吴庐山 in their paper "一种新的群体智能算法-狼群算法" at Systems Engineering and Electronics in 2013. 12 | In fact, they are 2 different kinds of algorithm. WPA was shown in this file, and WPS was in wps.py. 13 | 14 | Ref:git@github.com:xzltc/WPA.git 15 | Ref:https://blog.csdn.net/weixin_37978667/article/details/85112709 16 | >吴虎胜,张凤鸣,吴庐山.一种新的群体智能算法——狼群算法[J].系统工程与电子技术, 2013, 35(11): 2430-2438. 17 | >周强,周永权-种基于领导者策略的狼群搜索算法[J.计算机应用研究,2013,30(9):2629-2632. 18 | """ 19 | import numpy as np 20 | import math 21 | import random 22 | import heapq 23 | from test_func import * 24 | import matplotlib.pyplot as plt 25 | 26 | 27 | class wpa(): 28 | def __init__(self, pop_size=50, n_dim=2, alpha=4, beta=6, w=100, lb=-1e5, ub=1e5, max_iter=300, func=None): 29 | self.pop = pop_size 30 | self.n_dim = n_dim 31 | self.func = func 32 | self.max_iter = max_iter # max iter 33 | self.alpha = alpha # 探狼比例因子 (取[n/(α+1),n/α]之间的整数) 34 | self.beta = beta # 狼群更新比例因子 35 | self.w = w # 距离判定因子 36 | self.S = 1000 # 步长因子 37 | self.number_T = np.random.randint(self.pop / (self.alpha + 1), self.pop / self.alpha) # 探狼数量 38 | self.h = 10 # 探狼探寻方向总数 39 | self.T_max = 30 # 最大游走次数 40 | 41 | self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim) 42 | assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True' 43 | assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound' 44 | 45 | self.step_a = (self.ub - self.lb) / self.S # 探狼游走步长 46 | self.step_b = 2 * self.step_a # 猛狼奔袭步长 47 | self.step_c = self.step_a / 2 # 围攻步长 48 | 49 | self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim)) 50 | self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles 51 | 52 | self.pbest_x = self.X.copy() # personal best location of every particle in history 53 | self.pbest_y = [self.Y[i] for i in range(self.pop)] # best image of every particle in history 54 | self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles 55 | self.gbest_y = np.inf # global best y for all particles 56 | self.gbest_y_hist = [] # gbest_y of every iteration 57 | self.update_gbest() 58 | 59 | def update_pbest(self): 60 | ''' 61 | personal best 62 | :return: 63 | ''' 64 | # self.need_update = self.pbest_y > self.Y 65 | # print(self.need_update) 66 | # print(self.pbest_y) 67 | # print(self.Y) 68 | for i in range(len(self.Y)): 69 | if self.pbest_y[i] > self.Y[i]: 70 | self.pbest_x[i] = self.X[i] 71 | self.pbest_y[i] = self.Y[i] 72 | # self.pbest_x = np.where(self.need_update, self.X, self.pbest_x) 73 | # self.pbest_y = np.where(self.need_update, self.Y, self.pbest_y) 74 | # print(self.pbest_x) 75 | 76 | def update_gbest(self): 77 | ''' 78 | global best 79 | :return: 80 | ''' 81 | idx_min = self.pbest_y.index(min(self.pbest_y)) 82 | if self.gbest_y > self.pbest_y[idx_min]: 83 | self.gbest_x = self.X[idx_min, :].copy() 84 | self.gbest_y = self.pbest_y[idx_min] 85 | 86 | def update(self): 87 | L_Wolf_Y = np.min(self.Y) # 记录头狼的值 88 | L_Wolf_index = np.argmin(self.Y) # 头狼在狼群(wol)f_colony_X)中下标位置 89 | L_Wolf_X = self.X[L_Wolf_index] # 记录头狼的变量信息 90 | L_Wolf = [L_Wolf_Y, L_Wolf_index] 91 | 92 | # 初始化探狼 93 | T_Wolf_V = heapq.nsmallest(self.number_T, self.Y.copy()) 94 | T_Wolf = self.find_index(T_Wolf_V, self.Y) # 0:探狼在狼群中位置 1:解 95 | # 初始化猛狼 96 | M_Wolf_V = heapq.nlargest(self.pop - self.number_T - 1, self.Y.copy()) 97 | M_Wolf = self.find_index(M_Wolf_V, self.Y) # 0:探狼在狼群中位置 1:解 98 | self.detective_wolf(T_Wolf, L_Wolf_Y, L_Wolf_X, L_Wolf) 99 | # 需要修改,参考一种新的群体智能算法 狼群算法> 2013.11 式(3) 100 | # 言w增大会加速算法收敛,但W过大会使得人工狼很难进入围攻行为,缺乏对猎物的精细搜索。 101 | d_near = 0 102 | for d in range(self.n_dim): 103 | d_near += ((1 / (1 * self.w * self.n_dim)) * (self.ub[d] - self.lb[d])) # dnear值,判定距离 104 | self.call_followers(d_near, M_Wolf, L_Wolf_Y, L_Wolf_X, L_Wolf_index) 105 | self.siege(M_Wolf, L_Wolf_X, L_Wolf_Y, L_Wolf_index) 106 | self.live() 107 | 108 | def find_index(self, value, wolf_colony): 109 | ret = np.zeros((len(value), 2)) 110 | 111 | for i in range(0, len(value)): 112 | ret[i][0] = wolf_colony.index(value[i]) 113 | ret[i][1] = value[i] 114 | return ret 115 | 116 | def detective_wolf(self, T_Wolf, L_Wolf_Y, L_Wolf_X, L_Wolf): 117 | # 探狼开始游走 118 | for i in range(0, T_Wolf.shape[0]): 119 | H = np.random.randint(2, self.h) # 尝试的方向 120 | single_T_Wolf = self.X[int(T_Wolf[i][0])] # 当前探狼 121 | optimum_value = T_Wolf[i][1] # 游走的最优解 122 | optimum_position = single_T_Wolf.copy() # 游走最优位置 123 | find = False 124 | 125 | # 探狼游走行为 一旦探狼发现目标 -> 开始召唤 126 | for t in range(0, self.T_max): 127 | # 在初始位置朝H个方向试探,直到找到一个优解 128 | for p in range(1, H + 1): 129 | single_T_Wolf_trial = single_T_Wolf.copy() 130 | # 一种新的群体智能算法 狼群算法> 2013.11 式(1) 131 | # h越大探狼搜寻得越精细但同时速度也相对较慢 132 | # 这个部分有点像果蝇的搜素 133 | single_T_Wolf_trial = single_T_Wolf_trial + math.sin(2 * math.pi * p / H) * self.step_a # 根据原式不需要转化类型为int 134 | # 一种基于领导者策略的狼群搜索算法> 2013.9 式(2) 135 | # single_T_Wolf_trial = single_T_Wolf_trial + np.random.uniform(-1, 1,(single_T_Wolf_trial.shape[0],)) * self.step_a 136 | 137 | single_T_Wolf_V = self.func(single_T_Wolf_trial) # [0] 138 | 139 | # 探狼转变为头狼 140 | if L_Wolf_Y > single_T_Wolf_V: 141 | find = True 142 | L_Wolf_Y = single_T_Wolf_V # 更新头狼解 143 | L_Wolf_X = single_T_Wolf_trial 144 | L_Wolf_index = int(T_Wolf[i][0]) # 更新头狼下标 145 | self.X[L_Wolf_index] = single_T_Wolf_trial # 更新头狼位置参数 146 | 147 | T_Wolf = np.delete(T_Wolf, i, axis=0) # 探狼转为头狼,发起召唤,删除探狼 148 | break 149 | 150 | elif optimum_value > single_T_Wolf_V: 151 | optimum_value = single_T_Wolf_V 152 | optimum_position = single_T_Wolf_trial 153 | 154 | else: 155 | # print(" > 第%d只探狼完成第%d次游走,未发现猎物" % ((i + 1), (t + 1))) # 记录上次的最优位置 156 | single_T_Wolf = optimum_position 157 | 158 | if find is True: 159 | break 160 | 161 | if find is True: 162 | print("第%d只探狼发现猎物 %f" % (i, single_T_Wolf_V)) 163 | break 164 | 165 | else: 166 | # 若游走完成探狼没找到猎物,更新所有游走过程中最优的一次位置 167 | self.X[int(T_Wolf[i][0])] = optimum_position 168 | 169 | def call_followers(self, d_near, M_Wolf, L_Wolf_Y, L_Wolf_X, L_Wolf_index): 170 | # 召唤行为 171 | surrounded = False 172 | # 所有猛狼进入围攻范围才能结束 173 | while ~surrounded: 174 | ready = 0 175 | for m in range(0, M_Wolf.shape[0]): 176 | s_m_index = int(M_Wolf[m][0]) # 猛狼在狼群中下标 177 | single_M_Wolf = self.X[s_m_index] # 猛狼变量 178 | d = np.abs(L_Wolf_X - single_M_Wolf) 179 | dd = np.sum(d) 180 | 181 | while d_near < dd: 182 | for d in range(self.n_dim): 183 | single_M_Wolf[d] = single_M_Wolf[d] + self.step_b[d] * (L_Wolf_X[d] - single_M_Wolf[d]) / np.abs(L_Wolf_X[d] - single_M_Wolf[d]) 184 | single_M_Wolf_V = self.func(single_M_Wolf) 185 | 186 | # 更新猛狼位置 187 | self.X[s_m_index] = single_M_Wolf 188 | M_Wolf[m][1] = single_M_Wolf_V 189 | 190 | d = np.abs(L_Wolf_X - single_M_Wolf) 191 | dd = np.sum(d) 192 | 193 | if L_Wolf_Y > single_M_Wolf_V: 194 | # 头狼变猛狼 195 | M_Wolf[m][0] = L_Wolf_index 196 | M_Wolf[m][1] = L_Wolf_Y 197 | self.X[L_Wolf_index] = L_Wolf_X 198 | 199 | # 猛狼变头狼 200 | L_Wolf_Y = single_M_Wolf_V 201 | L_Wolf_X = single_M_Wolf 202 | L_Wolf_index = s_m_index 203 | self.X[L_Wolf_index] = single_M_Wolf 204 | break 205 | 206 | if d_near > dd: 207 | ready += 1 # 围攻就绪态+1 208 | else: 209 | break 210 | 211 | # 所有猛狼是否就位 212 | if ready == M_Wolf.shape[0]: 213 | print(" > 所有猛狼已进入围攻状态") 214 | break 215 | 216 | def siege(self, M_Wolf, L_Wolf_X, L_Wolf_Y, L_Wolf_index): 217 | for m in range(0, M_Wolf.shape[0]): 218 | s_m_index = int(M_Wolf[m][0]) 219 | single_M_Wolf = self.X[s_m_index] 220 | # 发起围攻,计算围攻后位置 221 | single_M_Wolf = single_M_Wolf + np.random.uniform(-1, 1) * self.step_c * np.abs(L_Wolf_X - single_M_Wolf) 222 | single_M_Wolf_V = self.func(single_M_Wolf) 223 | 224 | if L_Wolf_Y > single_M_Wolf_V: 225 | print(" > 发起围攻!目标更新 原值:%f => 现值:%f" % (L_Wolf_Y, single_M_Wolf_V)) 226 | # 头狼变猛狼 227 | M_Wolf[m][0] = L_Wolf_index 228 | M_Wolf[m][1] = L_Wolf_Y 229 | self.X[L_Wolf_index] = L_Wolf_X 230 | 231 | # 猛狼变头狼 232 | L_Wolf_Y = single_M_Wolf_V 233 | L_Wolf_X = single_M_Wolf 234 | L_Wolf_index = s_m_index 235 | self.X[L_Wolf_index] = single_M_Wolf 236 | if self.gbest_y > single_M_Wolf_V: 237 | self.gbest_y = single_M_Wolf_V 238 | self.gbest_x = single_M_Wolf 239 | self.gbest_y_hist.append(self.gbest_y) 240 | else: 241 | self.gbest_y_hist.append(self.gbest_y) 242 | 243 | 244 | def live(self): 245 | # 强者生存行为 246 | wolf_colony_V = [self.func(self.X[i]) for i in range(len(self.X))] # 重新计算现在所有狼狩猎的状态 247 | eliminate_number = np.random.randint(self.pop / (2 * self.beta), self.pop / self.beta) 248 | Bad_Wolf_V = heapq.nlargest(eliminate_number, wolf_colony_V.copy()) 249 | Bad_Wolf = self.find_index(Bad_Wolf_V, wolf_colony_V) 250 | # 生成新的人工狼 251 | new_wolf = np.random.uniform(self.lb, self.ub, (eliminate_number, self.n_dim)) 252 | # 淘汰最弱的狼 253 | for n in range(0, len(Bad_Wolf_V)): 254 | self.X[int(Bad_Wolf[n][0])] = new_wolf[n] 255 | 256 | def run(self): 257 | for i in range(self.max_iter): 258 | print(i) 259 | self.update() 260 | self.best_x, self.best_y = self.gbest_x, self.gbest_y 261 | return self.best_x, self.best_y 262 | 263 | if __name__ == '__main__': 264 | n_dim = 2 265 | lb = [-5.12 for i in range(n_dim)] 266 | ub = [5.12 for i in range(n_dim)] 267 | demo_func = f22 268 | # def __init__(self, pop_size=50, n_dim=2, alpha=4, beta=6, w=500, lb=-1e5, ub=1e5, max_iter=300, func=None): 269 | wpa = wpa(pop_size=50, n_dim=n_dim, max_iter=1000, lb=lb, ub=ub, func=demo_func, alpha=4, beta=6, w=500) 270 | wpa.run() 271 | print('best_x is ', wpa.gbest_x, 'best_y is', wpa.gbest_y) 272 | # f22 is best_x is [ 0.09110638 -0.71978079] best_y is -1.0312114438653428 273 | # f23 is best_x is [-448.40744098 403.16544094] best_y is -894.7260832993893 效果不行 274 | print(f'{demo_func(wpa.gbest_x)}\t{wpa.gbest_x}') 275 | plt.plot(wpa.gbest_y_hist) 276 | plt.show() 277 | --------------------------------------------------------------------------------