蚁群算法 遗传算法 免疫算法

遗传算法(一元)

(解一元函数极值)

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from math import *
from numpy import *

#目标函数
def y(fun,x):
    return eval(fun)

#生成初始种群
def init_pop(num,DNA_SIZE):
    pop = np.random.randint(2,size = [num,DNA_SIZE])
    return pop

#计算适应度
def get_fitness(pop,choice):
    gene = np.array([2 ** i for i in range(DNA_SIZE)])
    result = np.dot(pop,gene.T)
    fitness = y(fun,result * (limit[1] - limit[0]) / (2 ** DNA_SIZE) + limit[0])
    if choice == 'max':
        return (fitness - np.min(fitness) + 1e-3)
    elif choice == 'min':
        return (np.max(fitness) - fitness + 1e-3)

#自然选择
def select(pop,fitness):
    index = np.random.choice(len(pop),size = int(len(pop) * 0.8),replace = True,p = fitness / fitness.sum())
    return pop[index]

#交叉和变异
def cross_and_mutate(pop,CROSS_RATE):
    new_pop = []
    for father in pop:
        child = father
        if np.random.rand() <= CROSS_RATE:
            mother = pop[np.random.randint(len(pop))]
            point = np.random.randint(DNA_SIZE)
            child[point:] = mother[point:]
            mutate(child,MUTATE_RATE)
        new_pop.append(child)
    return new_pop

#变异
def mutate(child,MUTATE_RATE):
    if np.random.rand() <= MUTATE_RATE:
        point = np.random.randint(DNA_SIZE)
        child[point] = child[point] ^ 1


num = 100000  #初始种群数量
DNA_SIZE = 10 #DNA长度
fun = 'sin(x) + sin(2 * x) + cos(x ** 2) + x - x ** 2 - x ** 3  + exp(x)' #函数表达式
limit = [-2,5] #取值范围
choice = 'max' #最大值或最小值
CROSS_RATE = 0.8 #发生交叉的概率
MUTATE_RATE = 0.003 #发生交叉的概率
N_GENERATION = 100 #繁殖代数

# fun = input('输入关于x的表达式(如:x ** 2 + 2 * x + 3):')
# num = int(input('输入初始种群数:'))
# DNA_SIZE = int(input('输入DNA长度:'))
# low = float(input('输入下限:'))
# high = float(input('输入上限:'))
# limit = [low,high]
# choice = input('输入所求为最大值或最小值(最大值:max,最小值:min):')
# CROSS_RATE = float(input('输入交叉概率(0.6~1.0):'))
# MUTATE_RATE = float(input('输入变异概率(0~0.1):'))
# N_GENERATION = int(input('输入遗传代数:'))


pop = init_pop(num, DNA_SIZE)
for i in range(N_GENERATION):
    fitness = get_fitness(pop,choice)
    pop = select(pop,fitness)
    pop = np.array(cross_and_mutate(pop,CROSS_RATE))
    if len(pop) <= 5:
        break


gene = np.array([2 ** i for i in range(DNA_SIZE)])
result = np.dot(pop,gene.T)
result_x = result * (limit[1] - limit[0]) / (2 ** DNA_SIZE) + limit[0]
result_y = y(fun,result_x)
print('最优解为:',result_x,end = '\n')
print('对应函数值为:',result_y,end = '\n')

x = np.arange(limit[0],limit[1],(limit[1] - limit[0]) / 50)
fx = y(fun,x)
plt.figure(figsize = (20,8),dpi = 80)
plt.title('Genetic Algorithm',fontsize = '20')
plt.xlabel('x',fontsize = 20)
plt.ylabel('y',rotation = 'horizontal',fontsize = 20)
plt.plot(x,fx,color = 'green',label = 'y = ' + fun)
plt.scatter(result_x,result_y,color = 'red',label = 'best_x')
plt.legend(loc = 'lower right',fontsize = 15,framealpha = 0.3)
plt.show()

 

遗传算法(二元)

(解二元函数极值)

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from math import *
from numpy import *

#目标函数
def f(fun,x,y):
    return eval(fun)

#生成初始种群
def init_pop(num,DNA_SIZE):
    pop = np.random.randint(2,size = [2,num,DNA_SIZE])
    return pop

#计算适应度
def get_fitness(pop,choice):
    gene = np.array([2 ** i for i in range(DNA_SIZE)])
    result_x = np.dot(pop[0],gene.T)
    result_y = np.dot(pop[1], gene.T)
    fitness = f(fun,result_x * (limit_x[1] - limit_x[0]) / (2 ** DNA_SIZE) + limit_x[0],result_y * (limit_y[1] - limit_y[0]) / (2 ** DNA_SIZE) + limit_y[0])
    if choice == 'max':
        return (fitness - np.min(fitness) + 1e-3)
    elif choice == 'min':
        return (np.max(fitness) - fitness + 1e-3)

#自然选择
def select(pop,fitness):
    index = np.random.choice(len(pop[0]),size = int(len(pop[0]) * 0.9),replace = True,p = fitness / fitness.sum())
    return np.array([pop[0][index],pop[1][index]])

#交叉和变异
def cross_and_mutate(pop,CROSS_RATE):
    new_pop = [[],[]]
    for father1,father2 in list(zip(pop[0],pop[1])):
        child1 = father1
        child2 = father2
        mother1, mother2 = pop[[0,1],np.random.randint(len(pop))]
        if np.random.rand() <= CROSS_RATE:
            point = np.random.randint(DNA_SIZE)
            child1[point:] = mother1[point:]
            mutate(child1,MUTATE_RATE)
        if np.random.rand() <= CROSS_RATE:
            point = np.random.randint(DNA_SIZE)
            child2[point:] = mother2[point:]
            mutate(child2, MUTATE_RATE)
        new_pop[0].append(child1)
        new_pop[1].append(child2)
    return new_pop

#变异
def mutate(child,MUTATE_RATE):
    if np.random.rand() <= MUTATE_RATE:
        point = np.random.randint(DNA_SIZE)
        child[point] = child[point] ^ 1


num = 100000  #初始种群数量
DNA_SIZE = 10 #DNA长度
# fun = '3 * (1 - x) ** 2 * np.exp(-(x ** 2) - (y + 1) ** 2)- 10 * (x / 5 - x ** 3 - y ** 5) * np.exp(-x ** 2 - y ** 2)- 1 / 3 ** np.exp(-(x + 1) ** 2 - y ** 2)' #函数表达式
# limit_x = [-2,3] #取值范围
# limit_y = [-3,6]
fun = '5 * sin(x * y) + x ** 2 + y ** 2'
limit_x = [-4,4] #取值范围
limit_y = [-4,4]
choice = 'max' #最大值或最小值
CROSS_RATE = 0.8 #发生交叉的概率
MUTATE_RATE = 0.05 #发生交叉的概率
N_GENERATION = 1000 #繁殖代数
iter_time = 50 #运行次数,防止陷入局部最优解

# fun = input('输入关于x,y的表达式(如:x ** 2 + 2 * x + 3 + y):')
# num = int(input('输入初始种群数:'))
# DNA_SIZE = int(input('输入DNA长度:'))
# low_x = float(input('输入x下限:'))
# high_x = float(input('输入x上限:'))
# limit_x = [low_x,high_y]
# low_y = float(input('输入y下限:'))
# high_y = float(input('输入y上限:'))
# limit_y = [low_y,high_y]
# choice = input('输入所求为最大值或最小值(最大值:max,最小值:min):')
# CROSS_RATE = float(input('输入交叉概率(0.6~1.0):'))
# MUTATE_RATE = float(input('输入变异概率(0~0.1):'))
# N_GENERATION = int(input('输入遗传代数:'))

scatter_x = limit_x[0]
scatter_y = limit_y[0]
scatter_z = f(fun,scatter_x,scatter_y)
for time in range(iter_time):
    pop = init_pop(50, DNA_SIZE)
    for i in range(N_GENERATION):
        fitness = get_fitness(pop,choice)
        pop = select(pop,fitness)
        pop = np.array(cross_and_mutate(pop,CROSS_RATE))
        if len(pop[0]) <= 5:
            break
    gene = np.array([2 ** i for i in range(DNA_SIZE)])
    result_x = np.dot(pop[0], gene.T) * (limit_x[1] - limit_x[0]) / (2 ** DNA_SIZE) + limit_x[0]
    result_y = np.dot(pop[1], gene.T) * (limit_y[1] - limit_y[0]) / (2 ** DNA_SIZE) + limit_y[0]
    result_z = f(fun, result_x, result_y)
    if choice == 'min':
        min_index = np.argmin(result_z)
        if result_z[min_index] <= scatter_z:
            scatter_x = result_x[min_index]
            scatter_y = result_y[min_index]
            scatter_z = result_z[min_index]
    elif choice == 'max':
        max_index = np.argmax(result_z)
        if result_z[max_index] >= scatter_z:
            scatter_x = result_x[max_index]
            scatter_y = result_y[max_index]
            scatter_z = result_z[max_index]

print('最优解:','x = ',scatter_x,'y = ',scatter_y,end = '\n')
print('结果:','z = ',scatter_z)

x = np.arange(limit_x[0],limit_x[1],(limit_x[1] - limit_x[0]) / 50)
y = np.arange(limit_y[0],limit_y[1],(limit_y[1] - limit_y[0]) / 50)
x,y = np.meshgrid(x,y)
z = f(fun,x,y)

# 新建一个画布
figure = plt.figure(figsize = (10,8),dpi = 80)
# 新建一个3d绘图对象
ax = Axes3D(figure)
# 定义x,y 轴名称
plt.xlabel("x")
plt.ylabel("y")
# 设置间隔和颜色
ax.scatter(scatter_x,scatter_y,scatter_z,color = 'red')
ax.plot_surface(x,y,z, rstride=1, cstride=1, color ="green",alpha = 0.5)
# 展示
plt.show()

 

免疫算法

(找二元函数极值)

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from numpy import *


G = 100    #迭代次数
fun = '5 * sin(x * y) + x ** 2 + y ** 2'   #目标函数
choice = 'max'
dim = 2                    #维度
limit_x = [-4,4]           #x取值范围
limit_y = [-4,4]           #y取值范围
pop_size = 10              #种群规模
mutate_rate = 0.7          #变异概率
delta = 0.2                #相似度阈值
beta = 1                   #激励度系数
colone_num = 10            #克隆份数
if choice == 'max':
    alpha = 2              #激励度系数,求最大值为正,最小值为负
else:
    alpha = -2

def f(fun,x,y):
    return eval(fun)

#初始化种群
def init_pop(dim,pop_size,*limit):
    pop = np.random.rand(dim,pop_size)
    for i in range(dim):
        pop[i,:] *= (limit[i][1] - limit[i][0])
        pop[i,:] += limit[i][0]

    return pop

#计算浓度
def calc_density(pop,delta):
    density = np.zeros([pop.shape[1],])
    for i in range(pop.shape[1]):
        density[i] = np.sum(len(np.ones([pop.shape[1],])[np.sqrt(np.sum((pop - pop[:,i].reshape([2,1])) ** 2,axis = 0)) < delta]))
    return density / pop.shape[1]

#计算激励度
def calc_simulation(simulation,density):
        return (alpha * simulation - beta * density)


#变异,随着代数增加变异范围逐渐减小
def mutate(x,gen,mutata_rate,dim,*limit):
    for i in range(dim):
        if np.random.rand() <= mutata_rate:
            x[i] += (np.random.rand() - 0.5) * (limit[i][1] - limit[i][0]) / (gen + 1)    #加上随机数产生变异
            if (x[i] > limit[i][1]) or (x[i] < limit[i][0]):      #边界检测
                x[i] = np.random.rand() * (limit[i][1] - limit[i][0]) + limit[i][0]


pop = init_pop(dim,pop_size,limit_x,limit_y)
init_simulation = f(fun,pop[0,:],pop[1,:])
density = calc_density(pop,delta)
simulation = calc_simulation(init_simulation,density)
# print(pop)
# print(init_simulation)
# print(calc_density(pop,delta))
#进行激励度排序
index = np.argsort(-simulation)
pop = pop[:,index]
new_pop = pop.copy()    #浅拷贝
simulation = simulation[index]


#免疫循环
for gen in range(G):
    best_a = np.zeros([dim,int(pop_size / 2)])   #用于保留每次克隆后亲和度最高的个体
    best_a_simulation = np.zeros([int(pop_size / 2),]) #保存激励度
    #选出激励度前50%的个体进行免疫
    for i in range(int(pop_size / 2)):
        a = new_pop[:,i].reshape([2,1])
        b = np.tile(a,(1,colone_num))   #克隆10份
        for j in range(colone_num):
            mutate(a,gen,mutate_rate,dim,limit_x,limit_y)
        b[:,0] = pop[:,i]       #保留克隆源个体
        #保留亲和度最高的个体
        b_simulation = f(fun,b[0,:],b[1,:])
        index = np.argsort(-b_simulation)
        best_a_simulation = b_simulation[index][0]    #最佳个体亲和度
        best_a[:,i] = b[:,index][:,0]                 #最佳个体
    #计算免疫种群的激励度
    a_density = calc_density(best_a,delta)
    best_a_simulation = calc_simulation(best_a_simulation,a_density)
    #种群刷新
    new_a = init_pop(2,int(pop_size / 2),limit_x,limit_y)
    #新生种群激励度
    new_a_simulation = f(fun,new_a[0,:],new_a[1,:])
    new_a_density = calc_density(new_a,delta)
    new_a_simulation = calc_simulation(new_a_simulation,new_a_density)
    #免疫种群与新生种群合并
    pop = np.hstack([best_a,new_a])
    simulation = np.hstack([best_a_simulation,new_a_simulation])
    index = np.argsort(-simulation)
    pop = pop[:,index]
    simulation = simulation[index]
    new_pop = pop.copy()


# 新建一个画布
figure = plt.figure(figsize = (10,8),dpi = 80)
# 新建一个3d绘图对象
ax = Axes3D(figure)
# 定义x,y 轴名称
plt.xlabel("x")
plt.ylabel("y")
for i in range(int(pop_size / 2)):
    ax.scatter(pop[0,i],pop[1,i],f(fun,pop[0,i],pop[1,i]),color = 'red')
    print('最优解:','x = ',pop[0,i],'y = ',pop[1,i],end = '\n')
    print('结果:','z = ',f(fun,pop[0,i],pop[1,i]))
x = np.arange(limit_x[0],limit_x[1],(limit_x[1] - limit_x[0]) / 50)
y = np.arange(limit_y[0],limit_y[1],(limit_y[1] - limit_y[0]) / 50)
x,y = np.meshgrid(x,y)
z = f(fun,x,y)
ax.plot_surface(x,y,z, rstride=1, cstride=1, color = 'green',alpha = 0.5)
plt.show()

 

蚁群算法

(解决TSP问题)

import numpy as np
from matplotlib import pyplot as plt

m = 50 #蚁群总数
alpha = 1  #信息度启发因子(重要程度)
beta = 2   #期望值启发因子(重要程度)
ratio = 0.6  #信息素挥发因子
num_epochs = 100 #迭代次数
Q = 80  #信息素总量
eps = 1e-5
city = [5.326,2.558,
   4.276,3.452,
   4.819,2.624,
   3.165,2.457,
   0.915,3.921,
   4.637,6.026,
   1.524,2.261,
   3.447,2.111,
   3.548,3.665,
   2.649,2.556,
   4.399,1.194,
   4.660,2.949,
   1.479,4.440,
   5.036,0.244,
   2.830,3.140,
   1.072,3.454,
   5.845,6.203,
   0.194,1.767,
   1.660,2.395,
   2.682,6.072]    #每个城市的x,y坐标

city = np.array(city).reshape((-1,2))
city_num = city.shape[0]  #城市的个数
distance = np.zeros((city_num,city_num))  #每个城市间的距离

def get_distance(route):   #传入路线,得到走过的总距离
   L = 0
   for i in range(len(route) - 1):
      L += distance[route[i],route[i + 1]]
   L += distance[route[-1],route[0]]

   return L

def get_delta_Tau(Tabu,L):  #传入禁忌表和每只蚂蚁的总路程,获得信息素改变量
   delta_Tau = np.zeros((city_num, city_num))  # 用于存放信息素改变量
   for i in range(m):
      for j in range(city_num - 1):
         delta_Tau[Tabu[i,j],Tabu[i,j + 1]] += Q / L[i]
      delta_Tau[Tabu[i,city_num - 1],Tabu[i,0]] += Q / L[i]

   return delta_Tau

for i in range(city_num):
   for j in range(city_num):
      if i == j:
         distance[i,j] = eps
      distance[i,j] = ((city[i][0] - city[j][0]) ** 2 + (city[i][1] - city[j][1]) ** 2) ** 0.5

Eta = 1. / distance  #城市之间的能见度
Tau = np.ones((city_num,city_num)) #信息素浓度矩阵
Tabu = np.zeros((m,city_num)).astype(int)   #禁忌表

Road = np.zeros((num_epochs,city_num))  #每次迭代的最佳路径
Road_Length = np.inf * np.ones((num_epochs,))  #每次最佳路径的长度
Road_Avg = np.zeros((num_epochs,))  #每次迭代路径的平均值

for epoch in range(num_epochs):
# 蚂蚁随机分布在20个城市中
   all_pos = []
   for i in range(np.ceil(m / city_num).astype(int)):
      pos = [i for i in range(city_num)]
      np.random.shuffle(pos)                  #每次将20个城市的顺序打乱
      all_pos.extend(pos)

   Tabu[:,0] = all_pos[:m]
# 蚂蚁转移
   for i in range(1,city_num): # i从第二个城市开始计数(初始化时已在某个城市)
      for j in range(m):
         visited = Tabu[j,0:i]   #已经去过的城市
         unvisited = np.zeros((city_num - i,)).astype(int) #没有去过的城市
         p = np.zeros_like(unvisited).astype(float) #存放去未去过的城市的概率
         index = 0
         for k in range(city_num):
            if k not in visited:
               unvisited[index] = k
               index += 1

         for k in range(len(p)):   #计算当前城市到未去过城市的概率
            p[k] = (Tau[visited[-1],unvisited[k]] ** alpha) * (Eta[visited[-1],unvisited[k]] ** beta)

         p = p / sum(p) #概率
         to_visit = unvisited[np.argmax(p)]  #前往概率最大的城市

         Tabu[j,i] = to_visit     #禁忌表上记录

   if epoch >= 1:   #将上一次找出的最优路径放入第一行
      Tabu[0,:] = Road[epoch - 1,:]

   #记录本次最佳的迭代路线
   L = np.zeros((m,1))   #记录每一只蚂蚁走过的总距离

   for k in range(m):
      route = Tabu[k,:]  #每只蚂蚁走过的路线
      L[k] = get_distance(route)

   Road_Length[epoch] = np.min(L)   #找出最短路程
   Road[epoch,:] = Tabu[np.argmin(L),:]  #找出最短路程的路径
   Road_Avg[epoch] = np.mean(L)     #记录平均路程

#更新信息素
   delta_Tau = get_delta_Tau(Tabu,L)
   Tau = (1 - ratio) * Tau + delta_Tau

#禁忌表清零
   Tabu = np.zeros((m,city_num)).astype(int)

print('最短路程为:',np.min(Road_Length))

#绘制最短路径
plt.figure(figsize = (20,8),dpi = 80)
plt.scatter(city[:,0],city[:,1],color = 'green')
route = Road[np.argmin(Road_Length),:].astype(int)
for i in range(len(route) - 1):
   plt.plot([city[route[i]][0],city[route[i + 1]][0]],[city[route[i]][1],city[route[i + 1]][1]],color = 'red')
plt.plot([city[route[0]][0],city[route[-1]][0]],[city[route[0]][1],city[route[-1]][1]],color = 'red')
plt.show()








 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值