遗传算法求三元函数极值(python)-采用实数编码3

这次代码的修改点在交叉变异 函数中,做了其他修改:

def crossover_and_mutation(pop, CROSSOVER_RATE=0.015):
    new_pop = []
    for i in range(POP_SIZE//2-20):
        fatherpoint = np.random.randint(low=0, high=POP_SIZE)
        child=pop[fatherpoint]
        motherpoint = np.random.randint(low=0, high=POP_SIZE)
        cross_points = np.random.randint(low=0, high=DNA_SIZE * 3)  # 随机产生交叉的点
        child[cross_points] = pop[motherpoint][cross_points]
        new_pop.append(child)


    for i in range(20):
        fatherpoint = np.random.randint(low=0, high=POP_SIZE)
        child = pop[fatherpoint]
        mutation(child, MUTATION_RATE=1)
        new_pop.append(child)

    # for father in pop:  # 遍历种群中的每一个个体,将该个体作为父亲
    #     child = father  # 孩子先得到父亲的全部基因
    #     if np.random.rand() < CROSSOVER_RATE:  # 产生子代时不是必然发生交叉,而是以一定的概率发生交叉
    #         # mother = pop[np.random.randint(POP_SIZE)]  # 再种群中选择另一个个体,并将该个体作为母亲
    #
    #         mother = pop[np.random.randint(POP_SIZE)]
    #
    #
    #         cross_points = np.random.randint(low=0, high=DNA_SIZE * 3)  # 随机产生交叉的点
    #         # child[cross_points:] = mother[cross_points:]  # 孩子得到位于交叉点后的母亲的基因
    #         child[cross_points] = mother[cross_points]
    #     else:
    #         mutation(child, MUTATION_RATE)  # mutation(child,MUTATION_RATE)每个后代有一定的机率发生变异
    #     new_pop.append(child)

    return new_pop

完整代码:

# x1*x1-x1*x2+x3
import numpy as np
import random

DNA_SIZE = 1
POP_SIZE = 100
CROSSOVER_RATE = 0.8
MUTATION_RATE = 0.015
N_GENERATIONS = 200
X_BOUND = [3.0, 5.0]  # x1
Y_BOUND = [2.1, 6.7]  # x2
Z_BOUND = [1.2, 9.6]  # x3


sum=0#测试变量


def F(x, y, z):
    val = x * x - x * y + z
    # print(val.shape) #(100,) 100 <class 'numpy.ndarray'>
    return val


def get_fitness(pop):
    x, y, z = translateDNA(pop)
    pred = F(x, y, z)
    return pred


def translateDNA(pop):  # pop表示种群矩阵,一行表示一个二进制编码表示的DNA,矩阵的行数为种群数目
    # x_pop = pop[:,0:DNA_SIZE]#这样的写法shape 是(3, 1) 31列 ndim维度是2(行,列 矩阵 )
    # 也可以认为是二维数组,有3行,每行有1个元素 size为3 [[3.18796615]\n [3.32110516]\n [4.34665405]]
    '''因为这样写x_pop = pop[:, 0:DNA_SIZE] shape是(3,1)是二维数组,所以会报"对象太深,无法容纳所需的数组"的错误,
    第一种解决方法是进行reshape,比如reshape(3,)即变成了一维数组,元素个数是3个,即语法是x_pop=pop[:,0:DNA_SIZE].reshape(POP_SIZE,)
    这时x_pop就变为[4.96893731 3.24515899 3.51500566] 一维数组

    第二种方法是在矩阵(二维数组)pop中直接选择某一列元素,比如  pop[:, 0],表示选择pop第0列所有的元素

    '''

    x_pop = pop[:,0]  # 取前DNA_SIZE个列表示x 这样的写法shape是(3,) ndim维度是1 一维数组 ,数组元素有3个 size为3 [4.28040552 3.25412449 4.61336022]
    # print(x_pop.shape)
    y_pop = pop[:, 1]  # 取中间DNA_SIZE个列表示y
    z_pop = pop[:, 2]  # 取后DNA_SIZE个列表示z
    # print(x_pop)

    return x_pop, y_pop, z_pop


def mutation(child, MUTATION_RATE):
    if np.random.rand() < MUTATION_RATE:  # 以MUTATION_RATE的概率进行变异
        mutate_point = np.random.randint(0, DNA_SIZE * 3)  # 随机产生一个实数,代表要变异基因的位置
        if mutate_point == 0:
            child[mutate_point] = np.random.uniform(3.0, 5.0)
        elif mutate_point == 1:
            child[mutate_point] = np.random.uniform(2.1, 6.7)
        else:
            child[mutate_point] = np.random.uniform(1.2, 9.6)


def crossover_and_mutation(pop, CROSSOVER_RATE=0.015):
    new_pop = []
    for i in range(POP_SIZE//2-20):
        fatherpoint = np.random.randint(low=0, high=POP_SIZE)
        child=pop[fatherpoint]
        motherpoint = np.random.randint(low=0, high=POP_SIZE)
        cross_points = np.random.randint(low=0, high=DNA_SIZE * 3)  # 随机产生交叉的点
        child[cross_points] = pop[motherpoint][cross_points]
        new_pop.append(child)


    for i in range(20):
        fatherpoint = np.random.randint(low=0, high=POP_SIZE)
        child = pop[fatherpoint]
        mutation(child, MUTATION_RATE=1)
        new_pop.append(child)

    # for father in pop:  # 遍历种群中的每一个个体,将该个体作为父亲
    #     child = father  # 孩子先得到父亲的全部基因
    #     if np.random.rand() < CROSSOVER_RATE:  # 产生子代时不是必然发生交叉,而是以一定的概率发生交叉
    #         # mother = pop[np.random.randint(POP_SIZE)]  # 再种群中选择另一个个体,并将该个体作为母亲
    #
    #         mother = pop[np.random.randint(POP_SIZE)]
    #
    #
    #         cross_points = np.random.randint(low=0, high=DNA_SIZE * 3)  # 随机产生交叉的点
    #         # child[cross_points:] = mother[cross_points:]  # 孩子得到位于交叉点后的母亲的基因
    #         child[cross_points] = mother[cross_points]
    #     else:
    #         mutation(child, MUTATION_RATE)  # mutation(child,MUTATION_RATE)每个后代有一定的机率发生变异
    #     new_pop.append(child)

    return new_pop


def getbest(pop, fitness):
    best_indiv = []
    fitness = get_fitness(pop)
    max_fitness_index = np.argmax(fitness)
    pop_copy_max = pop[max_fitness_index]
    best_indiv.append(pop_copy_max)
    # print(best_indiv)
    return max_fitness_index
def getworst(pop,fitness):
    worst_indiv = []
    fitness = get_fitness(pop)
    min_fitness_index = np.argmin(fitness)
    pop_copy_min = pop[min_fitness_index]
    worst_indiv.append(pop_copy_min)
    return min_fitness_index


def choicebyyang(arr, size, replace, p):
    for i in range(size):

        aa = np.random.rand()
        sum = 0
        for j in range(size):
            sum = sum + p[j]  # 累加概率
            if sum >= aa:
                break

        arr[i] = j
    return arr


def select(pop, fitness):  # nature selection wrt pop's fitness
    # fitnew=fitness.copy() #深拷贝
    fitnew = fitness
    # print('fitness',id(fitness))# 赋值操作在Python里是浅拷贝,两个变量地址一样
    # print('fitnew',id(fitnew))
    # print(id(fitnew)==id(fitness)) #True
    fitnew = fitnew + 1e-3 - np.min(fitnew)
    p = (fitnew) / (fitnew.sum())
    # print(np.arange(POP_SIZE))  #产生的是一维数组[0 1 2 ...100]
    # idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True, p=p)
    # 从0~POP_SIZE这个序列里随机取样 如果[pop_size]是一维数组,就表示从这个一维数组中随机采样,采size个,上面这行是全采用
    idx = choicebyyang(np.arange(POP_SIZE), size=POP_SIZE, replace=True, p=p) #一维数组
    bestindex = getbest(pop, fitness) #最优个体下标
    worstindex=getworst(pop,fitness) #最差个体下标


    # new_idx=[bestindex,worstindex] #<class 'list'>: [0, 1]
    # new_idx=[idx]+[bestindex,worstindex] #<class 'list'>: [array([0, 0, 0]), 0, 2]
    # new_idx = list(idx) + [bestindex, worstindex] #<class 'list'>: [0, 1, 1, 1, 2]
    new_idx=list(idx) #<class 'list'>: [2, 1, 2]
    half_pop_idx=new_idx[:POP_SIZE//2-2]
    half_pop_idx.append(bestindex)
    half_pop_idx.append(worstindex)

    half_pop_idx2=new_idx[POP_SIZE//2:]


    return pop[half_pop_idx],pop[half_pop_idx2] # 尽量选择适应值高的函数值的个体


'''
如果POP_SIZE=3,即种群个数是3,则从交叉,变异后的种群中,选择3个适应值高 pop[idx]=[2 0 0]的新个体去
更新pop种群,之后再进行不断的迭代,直到达到迭代次数终止。
'''


def print_info(pop):
    fitness = get_fitness(pop)
    max_fitness_index = np.argmax(fitness)
    print("max_fitness:", fitness[max_fitness_index])
    x, y, z = translateDNA(pop)

    print("最优的基因型:", pop[max_fitness_index])

    print("(x, y, z):", (x[max_fitness_index], y[max_fitness_index], z[max_fitness_index]))


if __name__ == "__main__":
    # pop1 = np.random.uniform(3.0, 5.0, size=(POP_SIZE, DNA_SIZE))  # matrix (POP_SIZE, DNA_SIZE)
    # pop2 = np.random.uniform(2.1, 6.7, size=(POP_SIZE, DNA_SIZE))
    # pop3 = np.random.uniform(1.2, 9.6, size=(POP_SIZE, DNA_SIZE))
    #
    # # print(type(pop1))# (100,1) 维度是2(行列 矩阵) <class 'numpy.ndarray'>
    # # pop={pop1,pop2,pop3}
    # pop = np.hstack((pop1, pop2, pop3)) #水平拼接
    # print(pop)
    '''
    [[3.44603448 4.51707625 7.90178727]
     [4.57616299 5.11309286 4.86911781]
     [3.24273815 2.9253602  4.45149325]
     ...
     [4.39321276 3.1657492  5.16654786]]
    '''
    # print(type(pop)) #<class 'numpy.ndarray'> n维数组
    # print(pop.shape) #(100,3) 矩阵有 100行,3列
    # print(pop.ndim) # 2 因为矩阵有行和列两个维度
    # print(pop.size) #300  矩阵共有300个元素
    # print(pop.dtype) #float64 矩阵元素类型是float64
# for i in range(100):#测试代码
    pop1 = np.random.uniform(3.0, 5.0, size=(POP_SIZE, DNA_SIZE))  # matrix (POP_SIZE, DNA_SIZE)
    pop2 = np.random.uniform(2.1, 6.7, size=(POP_SIZE, DNA_SIZE))
    pop3 = np.random.uniform(1.2, 9.6, size=(POP_SIZE, DNA_SIZE))

    # print(type(pop1))# (100,1) 维度是2(行列 矩阵) <class 'numpy.ndarray'>
    # pop={pop1,pop2,pop3}
    pop = np.hstack((pop1, pop2, pop3)) #水平拼接
    for _ in range(N_GENERATIONS):  # 迭代N代
        x, y, z = translateDNA(pop)  # 这句代码,我觉得没啥作用
        # print(x) #(100,) [4.82264692 4.04610252 4.92107325 4.49556859 3.1322498  3.60757363...] 一维数组100个数据
        # pop = np.array(crossover_and_mutation(pop, CROSSOVER_RATE))
        # print(pop.dtype)#<class 'numpy.ndarray'> (100, 3) 2 300 float64
        fitness = get_fitness(pop)

        # print(fitness) #<class 'numpy.ndarray'> (100,) 一维数组 100
        pop_half,pop_half2 = select(pop, fitness)  # 选择生成新的种群 503列

        pop_half3=np.array(crossover_and_mutation(pop, CROSSOVER_RATE)) #503列

        pop=np.vstack((pop_half,pop_half3)) #纵向(上下拼接)拼接 1003print_info(pop)

    #测试 运行100次 的最大值平均值代码
#     i=i+1
#     print(i)
#     fitness = get_fitness(pop)
#     max_fitness_index = np.argmax(fitness)
#     sum=sum+fitness[max_fitness_index]
# print(sum/100.0)


'''#随机数-随机值
for i in range(10):
    i=np.random.rand()
    print(i)
    i=i+1
'''


  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
遗传算法是一种基于自然选择和遗传学原理的优化算法,可以用于函数极值问题。下面是遗传算法三元函数极值的步骤: 1.定义适应度函数:对于三元函数f(x1,x2,x3)=x1*x1-x1*x2+x3,我们可以将其作为适应度函数,即fitness(x1,x2,x3)=f(x1,x2,x3)。 2.初始化种群:随机生成一定数量的个体,每个个体由三个实数编码表示,即x1、x2、x3。 3.选择操作:采用轮盘赌选择算子,根据个体适应度大小选择优秀的个体。 4.交叉操作:采用单点交叉算子,对选出的个体进行交叉操作,生成新的个体。 5.变异操作:对新生成的个体进行变异操作,增加种群的多样性。 6.评估函数:计算每个个体的适应度值。 7.选择优秀个体:根据适应度值选择优秀的个体。 8.重复执行步骤3-7,直到达到预设的迭代次数或找到最优解。 下面是Python代码实现: ```python import random # 定义适应度函数 def fitness(x1, x2, x3): return x1 * x1 - x1 * x2 + x3 # 初始化种群 def init_population(pop_size): population = [] for i in range(pop_size): x1 = random.uniform(-10, 10) x2 = random.uniform(-10, 10) x3 = random.uniform(-10, 10) population.append((x1, x2, x3)) return population # 选择操作 def selection(population): fitness_list = [fitness(*individual) for individual in population] total_fitness = sum(fitness_list) probability_list = [fitness / total_fitness for fitness in fitness_list] selected_population = [] for i in range(len(population)): selected_individual = random.choices(population, weights=probability_list)[0] selected_population.append(selected_individual) return selected_population # 交叉操作 def crossover(population): offspring_population = [] for i in range(len(population)): parent1 = population[i] parent2 = random.choice(population) crossover_point = random.randint(0, 2) offspring = parent1[:crossover_point] + parent2[crossover_point:] offspring_population.append(offspring) return offspring_population # 变异操作 def mutation(population, mutation_rate): mutated_population = [] for individual in population: if random.random() < mutation_rate: mutated_individual = list(individual) mutated_individual[random.randint(0, 2)] += random.uniform(-1, 1) mutated_population.append(tuple(mutated_individual)) else: mutated_population.append(individual) return mutated_population # 遗传算法三元函数极值 def genetic_algorithm(pop_size, max_iter, mutation_rate): population = init_population(pop_size) for i in range(max_iter): selected_population = selection(population) offspring_population = crossover(selected_population) mutated_population = mutation(offspring_population, mutation_rate) population = mutated_population best_individual = max(population, key=lambda x: fitness(*x)) return best_individual # 测试 best_individual = genetic_algorithm(100, 1000, 0.1) print("最优解:", best_individual) print("最优解对应的函数值:", fitness(*best_individual)) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值