手写遗传算法

import math
import random
import numpy as np
import pandas as pd


class GA:
    """
    遗传算法
    """

    def __init__(self, train_rate=0.7, precision=4, min_=-10, max_=10, population=None):
        self.train_rate = train_rate
        self.precision = precision
        self.min_ = min_
        self.max_ = max_
        self.population = population

    @property
    def __gene_length__(self):
        """
        获取基因长度
        """
        return int(math.log2((self.max_ - self.min_) * 10 ** self.precision)) + 1

    def binary2float(self, n):
        """
        二进制转为小数
        """
        string_number1 = n if isinstance(n, str) else str(n)
        decimal = 0
        flag = False if '.' not in string_number1 else True
        if flag:
            string_integer, string_decimal = string_number1.split('.')
            for i in range(len(string_decimal)):
                decimal += 2 ** (-i - 1) * int(string_decimal[i])
            number2 = int(str(int(string_integer, 2))) + decimal
            return round(number2, self.precision)
        else:
            return int(string_number1, 2)

    def float2binary(self, num):
        """
        转化为二进制
        """
        if num == int(num):
            return '{:08b}'.format(int(num)) + '.' + '0' * self.precision
        else:
            integer = int(num)
            flo = num - integer
            integercom = '{:08b}'.format(integer)
            tem = flo
            tmpflo = []
            for i in range(self.precision):
                tem *= 2
                tmpflo += str(int(tem))
                tem -= int(tem)
            return integercom + '.' + ''.join(tmpflo)

    def chromosome(self):
        """
        染色体
        """
        return self.encode(self.population)

    def encode(self, population):
        """
        编码
        """
        df_ = pd.DataFrame(np.array(population))
        for row in range(df_.shape[0]):
            df_.loc[row, :] = df_.loc[row, :].apply(lambda x: self.float2binary(x))
        return df_

    def decode(self, df_b):
        """
        解码
        """
        for row in range(df_b.shape[0]):
            df_b.loc[row, :] = df_b.loc[row, :].apply(lambda x: self.binary2float(x))
        return df_b

    def gene_mutation(self, population, p=0.01):
        """
        基因突变
        """

        def temp_(n, p_):
            s = [('0' if i == '1' else '1') if random.uniform(0.0, 1.0) <= p_ else i for i in n]
            s.insert(-self.precision, '.')
            return ''.join(s)

        df_b = self.encode(population)
        for row in range(df_b.shape[0]):
            df_b.loc[row, :] = df_b.loc[row, :].apply(lambda x: x.replace('.', '')).apply(lambda x: temp_(n=x, p_=p))
        return df_b

    def fit_func(self, individual):
        """
        适应度函数 这里用测试用 log2(n)
        """
        return np.log2(individual[0])

    def select(self, df_f, method='fit_func'):
        """
        选择运算
        """
        method = getattr(self, method, None)
        if not method:
            raise ValueError(f'{type(self).__name__} has no method: {method}')
        population = df_f.to_numpy().tolist()
        fit_ = [method(po) for po in population]
        select_p = [round(i / sum(fit_), 17) for i in fit_]
        accumulative_p = []
        t_ = 0
        for i in select_p:
            t_ += i
            accumulative_p.append(t_)
        population_new = []
        for i, p_ in enumerate(accumulative_p):
            p_temp = random.uniform(0.0, 1.0)
            if p_temp - 1 / np.PINF <= p_:
                population_new.append(population[i])
            else:
                j = 0
                while True:
                    if p_temp - 1 / np.PINF <= accumulative_p[j]:
                        population_new.append(population[j])
                        break
                    j += 1
        df_f['fit'] = fit_
        df_f['select_p'] = select_p
        df_f['accumulative_p'] = accumulative_p
        df_f['population_res'] = population_new
        return population_new, df_f

    def cross(self, df_b, p=0.6):
        """
        交叉
        """
        row, col = df_b.shape
        pos = [r_ for r_ in range(len(df_b.loc[0, 0]))]
        for c_ in range(col):
            ls_ = [r_ for r_ in range(row)]
            p_ = random.uniform(0.0, 1.0)
            for rr_ in range(row//2):
                if p_ <= p:
                    pos_ = random.choice(pos)
                    r1 = random.choice(ls_)
                    ls_.remove(r1)
                    r2 = random.choice(ls_)
                    ls_.remove(r2)
                    temp_ = df_b.loc[r1, c_]
                    df_b.loc[r1, c_] = temp_[:pos_] + df_b.loc[r2, c_][pos_:]
                    df_b.loc[r2, c_] = df_b.loc[r2, c_][:pos_] + temp_[pos_:]
        return df_b


if __name__ == '__main__':
    population = [random.randint(1, 10) for i in range(10)]
    print(population)
    ga = GA(population=population)
    for i in range(1000):
        df_b = ga.encode(population)
        df_b = ga.cross(df_b, p=0.5)
        df_f = ga.decode(df_b)
        population, df_f = ga.select(df_f=df_f)
    print(population)
    print(df_f)


输出结果:

[5, 5, 9, 9, 7, 9, 8, 5, 5, 10]
[[10.0], [10.0], [10.0], [10.0], [10.0], [10.0], [10.0], [10.0], [10.0], [10.0]]
      0       fit  select_p  accumulative_p population_res
0  10.0  3.321928       0.1             0.1         [10.0]
1  10.0  3.321928       0.1             0.2         [10.0]
2  10.0  3.321928       0.1             0.3         [10.0]
3  10.0  3.321928       0.1             0.4         [10.0]
4  10.0  3.321928       0.1             0.5         [10.0]
5  10.0  3.321928       0.1             0.6         [10.0]
6  10.0  3.321928       0.1             0.7         [10.0]
7  10.0  3.321928       0.1             0.8         [10.0]
8  10.0  3.321928       0.1             0.9         [10.0]
9  10.0  3.321928       0.1             1.0         [10.0]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值