遗传算法求三元函数极值(python)

您所在的位置:网站首页 三元函数求极值步骤 遗传算法求三元函数极值(python)

遗传算法求三元函数极值(python)

2024-07-07 02:28| 来源: 网络整理| 查看: 265

想看实数编码编码的 博客地址遗传算法求三元函数极值(python)-采用实数编码 *

遗传算法求三元函数极值(python)-采用二进制编码

本文的遗传算法采用二进制编码求三元函数极值 所求函数为 在这里插入图片描述 要想使用遗传算法,首要任务是进行编码

传统的 GA 中, DNA 我们能用一串二进制来表示, 比如: DNA1 = [1, 1, 0, 1, 0, 0, 1] DNA2 = [1, 0, 1, 1, 0, 1, 1] 这里,我们仍然使用二进制编码,但是如何与我们的问题对应起来呢? 为什么会要用二进制编码, 我们之后在下面的内容中详细说明这样编码的好处. 但是长成这样的 DNA 并不好使用. 如果要将它解码, 我们可以将二进制转换成十进制, 比如二进制的 11 就是十进制的 3. 这种转换的步骤在程序中很好执行. 但是有时候我们会需要精确到小数, 其实也很简单, 只要再将十进制的数浓缩一下就好. 比如我有 1111 这么长的 DNA, 我们产生的十进制数范围是 [0, 15], 而我需要的范围是 [-1, 1], 我们就将 [0, 15] 缩放到 [-1, 1] 这个范围就好. 我们知道二进制很容易转十进制,再区间压缩以下,这样一个DNA和一个解一一映射。

def translateDNA(pop): return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2**DNA_SIZE-1) * X_BOUND[1]

例如,1 0 1 0 1 0 0 1 0 0 => (4+32+128+256)/(1024-1)*(5-0)=3.3 上面针对的单变量的编码,求解单变量的函数极值 其完整代码如下,这里照搬了别人的代码,后面我会给出引用地址, 用它主要是参考,并修改为求解三元函数极值的代码 单变量求函数极值:

""" Visualize Genetic Algorithm to find a maximum point in a function. 可视化遗传算法去找到一个函数的最高点 """ import numpy as np import matplotlib.pyplot as plt DNA_SIZE = 10 # DNA length POP_SIZE = 100 # population size,种群中个体数目 CROSS_RATE = 0.8 # mating probability (DNA crossover),0.8的概率进行交叉配对 MUTATION_RATE = 0.003 # mutation probability,变异强度 N_GENERATIONS = 200 #迭代次数 X_BOUND = [0, 5] # x upper and lower bounds,指定x的取值范围 def F(x): return np.sin(10*x)*x + np.cos(2*x)*x # to find the maximum of this function # find non-zero fitness for selection #我们都需要一个评估好坏的方程, 这个方程通常被称为 fitness适应度. #为了找到下面这个曲线当中的最高点. 那么这个 fitness 方程可以定义为高度, 越高的点, fitness 越高. def get_fitness(pred): return pred + 1e-3 - np.min(pred)#因为如果直接返回pred可能是负值,而我们在计算概率的时候不能为负值。 #要进行处理,np.min表示取最小,为最大的负数,可以使全部只变成正的;1e-3为了让float进行相除防止小数点后的数被省略 # convert binary DNA to decimal and normalize it to a range(0, 5) #对基因的翻译,如这里函数,x轴是实数,这里解释了如何将遗传0、1序列翻译成实数。用十进制二进制转换 #pop (population)是一个储存二进制 DNA 的矩阵, 他的 shape 是这样 (pop_size, DNA_size) #这里DNA_SIZE,X_BOUND是超参数 def translateDNA(pop): return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2**DNA_SIZE-1) * X_BOUND[1] #dot()函数是矩阵乘,而*则表示逐个元素相乘 #np.arange()函数返回一个有终点和起点的固定步长的排列 #pop.dot(2 ** np.arange(DNA_SIZE)[::-1])已经转换成十进制 #但是需要归一化到0~5,如有1111这么长的DNA,要产生的十进制数范围是[0, 15], 而所需范围是 [-1, 1],就将[0,15]缩放到[-1,1]这个范围 #a[::-1]相当于 a[-1:-len(a)-1:-1],也就是从最后一个元素到第一个元素复制一遍。所以你看到一个倒序 #np.arange(DNA_SIZE)[::-1]得到10,9,8,...,0 #这里进行优胜劣汰的选择步骤 #适者生存的 select() 很简单, 我们只要按照适应程度 fitness 来选 pop 中的 parent 就好. fitness 越大, 越有可能被选到. def select(pop, fitness): # nature selection wrt pop's fitness idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,p=fitness/fitness.sum()) #这里概率不能为负,所以pred要进行非负处理 #replace表示抽样后是否放回,这里为True表示有放回,则可能会出现相同的索引值 # p 就是选它的比例,按比例来选择适应度高的,也会保留一些适应度低的,因为也可能后面产生更好的变异 #np.random.choice表示从序列中取值 np.arange()函数返回一个有终点和起点的固定步长的排列 return pop[idx] #繁衍,交叉父母的基因 def crossover(parent, pop): # mating process (genes crossover) if np.random.rand() 十进制 x = x_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(X_BOUND[1]-X_BOUND[0])+X_BOUND[0] y = y_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(Y_BOUND[1]-Y_BOUND[0])+Y_BOUND[0] z = z_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(Z_BOUND[1]-Z_BOUND[0])+Z_BOUND[0] #print(x,z) return x,y,z

有两种求解三元函数极值的代码, 第一种是按照我自己的想法,在select操作中,关于概率的修改。 下面是我的求解三元函数极值的完整代码:

# x1*x2-x1*x2+x3 import numpy as np import random DNA_SIZE = 24 POP_SIZE = 100 CROSSOVER_RATE = 0.8 MUTATION_RATE = 0.015 N_GENERATIONS = 100 X_BOUND = [3.0,5.0]#x1 Y_BOUND = [2.1,6.7]#x2 Z_BOUND = [1.2,9.6]#x3 def F(x, y,z): val=x*x-x*y+z #print(val) ''' for index in range(len(val)): if val[index] (POP_SIZE,1)'''#二进制--->十进制 x = x_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(X_BOUND[1]-X_BOUND[0])+X_BOUND[0] y = y_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(Y_BOUND[1]-Y_BOUND[0])+Y_BOUND[0] z = z_pop.dot(2**np.arange(DNA_SIZE)[::-1])/float(2**DNA_SIZE-1)*(Z_BOUND[1]-Z_BOUND[0])+Z_BOUND[0] #print(x,z) return x,y,z def mutation(child, MUTATION_RATE=0.003): if np.random.rand() (POP_SIZE,1)''' # 二进制--->十进制 x = x_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (X_BOUND[1] - X_BOUND[0]) + X_BOUND[0] y = y_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (Y_BOUND[1] - Y_BOUND[0]) + Y_BOUND[0] z = z_pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2 ** DNA_SIZE - 1) * (Z_BOUND[1] - Z_BOUND[0]) + Z_BOUND[0] # print(x,z) return x, y, z def mutation(child, MUTATION_RATE=0.003): if np.random.rand()


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3