结合爬山算子的对数自适应排挤遗传算法LGCCGA python实现

import numpy as np
import random
from scipy.optimize import fsolve

‘’’
对数自适应排挤遗传算法LGCCGA
引入爬山算子
author:sugarMei
date:2020/7/7
version:1.0
‘’’
‘’’
n:种群个数
min_d:爬上距离下限
max_d:爬山距离上限
gens:迭代的最大次数
Vars:定义域大小
dimension:问题维度
fits:适应度值
delta:精度 编码时精度
mutation_prob:变异概率
cross_prob:交叉概率
‘’’

参数初始化

n = 500
Vars = [-10, 10]
dimension = 2
min_d = 0.000001
max_d = 0.001
gens = 500
fits = np.zeros(n)
mutation_prob = 0.05
delta = 0.0001
cross_prob = 0.7

Cross-in-tray函数表示

def CrossInTray(x1, x2):
fact1 = np.sin(x1) * np.sin(x2)
fact2 = np.exp(np.abs(100 - np.sqrt(x1 ** 2 + x2 ** 2) / np.pi))
res = -0.0001 * (np.abs(fact1 * fact2) + 1) ** 0.1
return res

编码长度

def getEncodeLength(var, delta):
lengths = []
# 由于两个变量的上下界一致 只需要计算一次
res = fsolve(lambda x: ((var[1] - var[0]) / delta - 2 ** x + 1), [20])
# 向上取整
length = int(np.ceil(res[0]))
lengths.append(length)
lengths.append(length)
# 返回list lengths[0]代表第一个变量的编码长度
return lengths

初始化种群

def initPopulation(length_dna, size):
tmp = np.zeros((size, length_dna))
for i in range(size):
# 对每一行 即一个个体进行随机初始化
tmp[i, :] = np.random.randint(0, 2, length_dna)
return tmp

二进制的解码 针对一个个体的解码

def decode(x, lengths, var, delta):
# 多少个变量
length = len(lengths)
tmp = np.zeros(length)
start = 0
for i in range(length):
# 解码的值
decimal = 0
# 次方
power = lengths[i] - 1
for j in range(start, lengths[i] + start):
decimal += x[j] * (2 ** power)
# 次方减1 进行下一计算
power -= 1
# 更新start
start += lengths[i]
value = var[0] + decimal * (var[1] - var[0]) / (2 ** lengths[i] - 1)
tmp[i] = value

return tmp

两个个体交叉运算 单点交叉

def crossover(x1, x2):
# 随机找到一个交叉点
crossPoint = np.random.randint(0, sum(lengthDna), 1)[0]
x1[:crossPoint], x2[:crossPoint] = x2[:crossPoint], x1[:crossPoint]
return x1, x2

变异运算

def mutation(x):
# print(x)
if np.random.random() < mutation_prob:
mutation_point = np.random.randint(0, sum(lengthDna), 1)[0]
x[mutation_point] = int(x[mutation_point]) ^ 1
return x

爬山算子计算

def climb(x, m):
# 定义8个方向 上下前后以及对角线
dx, dy = [0, 0, 1, -1, 1, 1, -1, -1], [1, -1, 0, 0, 1, -1, 1, -1]
# 线性自适应
d = min_d - (gens - m) / (gens - 1) * (min_d - max_d)

# 对x进行解码
value = decode(x, lengthDna, Vars, delta)
for i in range(len(dx)):
    new_x, new_y = value[0] + d, value[1] + d
    # 满足定义域
    if Vars[0] <= new_x <= Vars[1] and Vars[0] <= new_y <= Vars[1]:
        if CrossInTray(value[0], value[1]) > CrossInTray(new_x, new_y):
            new_x_y = [new_x, new_y]
            # 新值更好 将new_x、new_y数值编码
            # 定义新的二进制编码变量
            start = 0
            encode = np.zeros(sum(lengthDna))
            for j in range(len(lengthDna)):
                # 根据公式计算原始的decimal
                decimal = (2 ** lengthDna[j] - 1) * (new_x_y[j] - Vars[0]) / (Vars[1] - Vars[0])
                # 将十进制数转化为二进制数
                b = bin(int(decimal))[2:]
                # 补0操作
                for k in range(lengthDna[j] - len(b)):
                    b = "0" + b
                # 赋值操作
                for k in range(start, start + lengthDna[j]):
                    encode[k] = int(b[k - start])
                # 更新起始位置
                start += lengthDna[j]

            # print("encode", encode)
            return encode
return x

lengthDna = getEncodeLength(Vars, delta)
print(sum(lengthDna))
X = initPopulation(sum(lengthDna), n)
print(X[0])
print(decode(X[0], lengthDna, Vars, delta))
m = 2 # 当前遗传代数
allowed = [i for i in range(n)] # 随机选择允许选择的父代个体

计算所有的个体的适应度值

for i in range(n):
# 解码
tmp = decode(X[i], lengthDna, Vars, delta)
# 计算函数值
fits[i] = CrossInTray(tmp[0], tmp[1])

while m < gens:
allowed = [i for i in range(n)]
# 总共n个个体 每次随机选择两个 需要n/2次迭代
for i in range(int(n / 2)):
if np.random.random() < cross_prob:
# 从种群中随机选择两个个体作为父代
[idx1, idx2] = random.sample(allowed, 2)
# 从allowed中删除选中的父代序号
allowed.remove(idx1)
allowed.remove(idx2)
f1 = X[idx1]
f2 = X[idx2]

        # 对父代进行交叉运算 生成s1、s2
        s1, s2 = crossover(f1, f2)
        # 对子代进行变异运算
        s1, s2 = mutation(s1), mutation(s2)
        # 在对两个子代进行爬山算子计算
        s1, s2 = climb(s1, m), climb(s2, m)

        # 重新计算两个子代的是适应度值
        # 解码
        s_d_1, s_d_2 = decode(s1, lengthDna, Vars, delta), decode(s2, lengthDna, Vars, delta)
        # 计算适应度值
        s_f_1, s_f_2 = CrossInTray(s_d_1[0], s_d_1[1]), CrossInTray(s_d_2[0], s_d_2[1])

        # 计算两个父代与两个子代分别的欧式距离
        d1 = np.linalg.norm(f1 - s1)
        d2 = np.linalg.norm(f1 - s2)
        d3 = np.linalg.norm(f2 - s1)
        d4 = np.linalg.norm(f2 - s2)
        # print(d1, d2, d3, d4)
        # 排挤过程
        if d1 + d4 <= d2 + d3:
            if s_f_1 > fits[idx1]:
                X[idx1] = s1
            if s_f_2 > fits[idx2]:
                X[idx2] = s2
        else:
            if s_f_2 > fits[idx1]:
                X[idx1] = s2
            if s_f_1 > fits[idx2]:
                X[idx2] = s1

# 计算所有的个体的适应度值
for i in range(n):
    # 解码
    tmp = decode(X[i], lengthDna, Vars, delta)
    # 计算函数值
    fits[i] = CrossInTray(tmp[0], tmp[1])

m += 1
if min(fits) < -2.062:
    print("第", m, "次迭代", "最小值:", min(fits))
    print("具体坐标:", decode(X[np.argmin(fits)], lengthDna, Vars, delta))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值