进化算法——遗传算法之找曲线最高点

"""
Visualize Genetic Algorithm to find a maximum point in a function.
Visit my tutorial website for more: https://mofanpy.com/tutorials/
"""
import numpy as np
import matplotlib.pyplot as plt

DNA_SIZE = 10            # DNA length,dna长度
POP_SIZE = 100           # population size 初始种群大小
CROSS_RATE = 0.8         # mating probability (DNA crossover) 交叉的概率
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
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)
def translateDNA(pop): return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2**DNA_SIZE-1) * X_BOUND[1]


def select(pop, fitness):    # nature selection wrt pop's fitness
    #np.arrange(POP_SIZE)生成从[0,POP_SIZE)的步长为1的数组
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,
                           p=fitness/fitness.sum())
    #np.arrange(POP_SIZE)和fitness是同长一维数组,按照fitness的概率有放回的选择np.arrange(POP_SIZE)中的数,
    #其中的数字可能会重复,毕竟概率越大越容易选到
    return pop[idx] #按索引去选择pop的数组,numpy的数组除了可被整数索引还可以被数组索引


def crossover(parent, pop):     # mating process (genes crossover)
    if np.random.rand() < CROSS_RATE: #0.8的概率父亲选择一个母亲交叉配对
        i_ = np.random.randint(0, POP_SIZE, size=1)   #选取随机母亲下标索引      # select another individual from pop
        #随机选择一个dna长度的01数组
        cross_points = np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool)   # choose crossover points
        #父亲在cross_points下为1的地方换成pop的母亲的dna
        parent[cross_points] = pop[i_, cross_points]                            # mating and produce one child
    return parent

def mutate(child):
    for point in range(DNA_SIZE):
        if np.random.rand() < MUTATION_RATE:
            child[point] = 1 if child[point] == 0 else 0 #变异,在某个概率下将某些01互换
    return child


pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE))   # initialize the pop DNA
# 返回一个0,1数组,大小pop_size,长度dna_size

plt.ion()       # something about plotting 画动态图,开启交互模式
x = np.linspace(*X_BOUND, 200) #产生从0,5的等差数列,个数为200个
plt.plot(x, F(x)) #画出平滑的F(x)的曲线

for _ in range(N_GENERATIONS):
    F_values = F(translateDNA(pop))    # compute function value by extracting DNA

    # something about plotting
    if 'sca' in globals(): sca.remove() #'sca'判断是不是一个全局变量,如果是,则将其移除
    sca = plt.scatter(translateDNA(pop), F_values, s=200, lw=0, c='red', alpha=0.5);plt.pause(0.05)

    # GA part (evolution)
    fitness = get_fitness(F_values)
    print("Most fitted DNA: ", pop[np.argmax(fitness), :])
    pop = select(pop, fitness)
    pop_copy = pop.copy()
    for parent in pop:
        child = crossover(parent, pop_copy)
        child = mutate(child)
        parent[:] = child       # parent is replaced by its child


plt.ioff(); plt.show()

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值