新遗传算法

此前使用deap库提供的遗传算法,后发现几个不便之处

1.需要对特征进行编码,还需要对编码溢出情况进行处理

2.交配的算法每次都交换连续的一段基因

因此基于遗传算法的基本思路,写了新的遗传算法,进行了小优化:
较传统遗传算法的区别
1.适应度这里固定成了单向增大为适应
2.不用再给特征编码就能实现变异,特征分为两类,第一类是在一个范围内取值的连续变量,第二类是离散的在list中选择,详见tez类定义

使用方法:改写calfit函数变成自己的算法之后就能使用(注意适应度增大原则)

下面是所有的源代码,大家可以根据自己的需要进行使用和改写,代码结尾注释掉的几行是一个调用的例子,大家可以参考

# -*- coding: utf-8 -*-
"""
Created on Tue Jun 18 20:29:24 2024

@author: trader tom
"""
'''
新遗传算法
较传统遗传算法的区别
1.适应度这里固定成了单向增大为适应
2.不用再给特征编码就能实现变异,特征分为两类,第一类是在一个范围内取值的连续变量,第二类是离散的在list中选择,详见tez类定义

使用方法:改写calfit函数变成自己的算法之后就能使用(注意适应度增大原则)

'''

import random
import numpy as np
class tez:#特征类
    def __init__(self,fanwei:'一个list,可以是范围的两个数字,也可以是包含所有元素的list',model:'int 1为范围内任意数字,2为一个list随机选'):
        self.model=model
        self.fanwei=fanwei
    def born(self):#给value赋值
        if self.model==1:
            self.value=random.uniform(min(self.fanwei), max(self.fanwei))
        else:
            self.value=random.choice(self.fanwei)
            
class getis:#个体类 类
    def __init__(self,ltz:'特征的信息:list([特征范围,model])'):
        self.ltz=[tez(i[0],i[1]) for i in ltz]#把特征实例化
    def born(self):#随机生成个体
        [tz.born() for tz in self.ltz]
        return [tz.value for tz in self.ltz]
    def bianyi(self,n):#参数是特征的索引,完成特征变异
        self.ltz[n].born()
        return  self.ltz[n].value

class geti:#个体类
    def __init__(self,value:'特征的值的list',father:'getis类'):
        self.value=value
        self.fit=False#最开始的时候个体没有适应度
        self.father=father
    def bianyi(self):#变异后不能把原来的个体改变,而是应该产生新个体
        weizhi=random.randint(0,len(self.value)-1)
        value=self.value.copy()
        value[weizhi]=self.father.bianyi(weizhi)
        return value


class qun:#种群类
    def __init__(self,n:'数量',gs:'实例化的getis'):
        self.pop=[geti(gs.born(),gs) for _ in range(n)]
        



def fanzhi(g1,g2):#之前的繁殖是挨着的dna才会交换,这里面是随机的选dna  
    g3,g4=geti(g1.value,g1.father),geti(g2.value,g2.father)
    # 从列表中随机选择最多n-1个不同位置
    lwz = random.sample(list(range(len(g1.value))),random.randint(1,len(g1.value)-1))
    for wz in lwz:
        g3.value[wz],g4.value[wz]=g4.value[wz],g3.value[wz]
    return g3,g4
        


def sai(pop:'种群', k:'想保留的数量', tournsize:'锦标赛规模'):#锦标赛选拔
    chosen = []
    for i in range(k):
        aspirants = random.sample(pop,tournsize)#参加比赛的个体
        chosen.append(max(aspirants, key=lambda obj: obj.fit))#最强的入围
    return chosen

def calfit(geti):#定义一下适应度函数,注意,这里面要调整成越大越好
    value=geti.value
    return 1/sum([(1.5-i)**2 for i in value])

def znh(pop):#中南海,选出最强一个
    geti=max(pop, key=lambda obj: obj.fit)
    return geti.value

def var(pop,pb:'变异概率',pf:'繁殖概率'):#繁殖+变异
    nf=int(pf*len(pop))#繁殖次数
    for _ in range(nf):
        g1,g2=random.sample(pop,2)
        g3,g4=fanzhi(g1,g2)   
        pop+=[g3,g4]
    
    nb=int(pb*len(pop))#变异次数
    for _ in range(nb):
        g=random.choice(pop)
        g2=geti(g.bianyi(),g.father)
        pop.append(g2)
    
    return pop
    

def fanyan(ngen:'繁衍的代数',pop:'种群',tournsize:'锦标赛规模',pb:'变异概率',pf:'繁殖概率'):#繁衍函数
    k=len(pop)
    for g in pop:#把适应度的算出来
        if not g.fit:
            g.fit=calfit(g)
    for gen in range(ngen):
        
        
        #完成交配+变异
        pop = var(pop, pb, pf)
        
        for g in pop:#把适应度的算出来
            if not g.fit:
                g.fit=calfit(g)
        
        #选择过程,默认群体数量保持不变
        pop = sai(pop,k,tournsize)        
        
        lv=[g.fit for g in pop]#适应值列表
        lv.sort()
        
        print(f'第{gen+1}代繁衍结束,平均适应度为{np.mean(lv)},适应度中位数为{lv[k//2]}')

    return pop

# ================================================================
# 使用
# gs=getis([[[1,200],1],[[3,2,4,99,-50,1.5],2],[[1,20],1],[[1,22],1],[[11,22],1]])
# pop=qun(100,gs).pop
# pop=fanyan(200,pop,5,0.2,0.5)
# znh(pop)

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值