Python——遗传算法简介及其在二次分配中的运用(含详细源代码)

一、遗传算法简介

 

 

 

 

 

 

 

 

 

 

 

 二、二次分配问题描述

 

三、Python代码实现 

import math
import random
import matplotlib.pyplot as plt

def getPermutation(n, x): #n为全排列的数量,x为一个二进制数
        """
        这是一个逆康托函数
        """
        nums = []
        x = '0b' + x  #加上二进制标签才能利于后面的计算
        x = eval(x)
        for i in range(1,n+1):
            nums.append(i)
        x = x-1
        out = []
        while nums:
            p = x//math.factorial(len(nums)-1)
            try:
                out.append(nums[p])
            except:
                pass
            x = x-p*math.factorial(len(nums)-1) 
            
            try:
                nums.pop(p)
            except:
                pass
        return out


def init(n):  
    '''这是一个生成初始种群的函数'''
    Max = math.factorial(n)  #Max是全排列的最大个数
    max_n = len(bin(Max)) - 2  #max_n为一个染色体的长度
    cs = []
    individual = 100
    for i in range(individual):
        x = random.randint(1, Max)
        x = str(bin(x)[2:])
        len_x = len(x)
        x = '0'*(max_n - len_x) + x  #没有到长度前面用0补齐
        cs.append(x)
    return cs

def fitness(cs,n,v1,v2): #cs中每一个元素对应一个值
    '''这是一个计算目标函数值的函数'''
    fitness1 = []  #将值存在fitnees1[]中
    for i in cs:
        loca = getPermutation(n,i) #用逆康托函数求出全排列列表
        cost_sum = 0
        #二维矩阵遍历
        for j in range(n):
            for k in range(n):
                loca1 = loca.index(j+1)
                loca2 = loca.index(k+1)
                cost = v2[j][k]*v1[loca1][loca2]  #核心的计算函数
                cost_sum = cost_sum + cost
        fitness1.append(cost_sum)
    return fitness1


def filter_max(cs,fitness1):
    '''这是一个筛选函数'''
    out = 80 #out为一次剔除的个体数
    for i in range(out):
        x = max(fitness1)
        index = fitness1.index(x)
        
        fitness1.pop(index)
        cs.pop(index)
    return cs,fitness1


def cross(cs,fitness1):
    '''
    交叉函数,传入cs,返回cs
    '''
    out = 80  #与剔除函数保持一致
    for  i in range(out):
        proba = random.randint(1,10000)
        y = len(cs)
        #print('len(y):',y)
        z = len(cs[0])
        if proba >= 900: #依据概率交叉
            #随机找两个个体交叉
            index1 = random.randint(0,y-1)
            index2 = random.randint(0,y-1)
            cs1 = str(cs[index1])
            cs2 = str(cs[index2])
            new1 = cs1[0:17] + cs2[0:z-17]
            cs.append(new1) 
        else:
            index = fitness1.index(min(fitness1))
            cs_new = cs[index]
            cs.append(cs_new) 
    return cs
    
    
    
def Mutation(cs,fitness1): #cs为种群
    '''变异函数
   传入一个种群,返回一个种群'''
    proba = random.randint(1,10000)
    index = fitness1.index(min(fitness1))
    if proba > 100:
        y = len(cs)
        max_n = len(cs[0])
        r1 = random.randint(0,y-1)
        
        r2 = random.randint(0,max_n-1)
        if r1 != index:
            cs_i = list(cs[r1])  #cs_i为被操作的基因
            x = int(cs_i[r2])
            cs_i[r2] = str(1-x)  
            cs_i = ''.join(cs_i)
            
            cs[r1] = cs_i
    return cs


if __name__ == '__main__':
    
    v1 = [[0 ,1 , 2 , 2 , 3 , 4 , 4 , 5 , 3 , 5 , 6 , 7],
      [1,  0 , 1 , 1 , 2 , 3 , 3 , 4 , 2 , 4 , 5 , 6],
      [2 , 1 , 0 , 2 , 1 , 2 , 2 , 3 , 1 , 3 , 4 , 5],
      [2 , 1 , 2 , 0 , 1 , 2 , 2 , 3 , 3 , 3 , 4 , 5],
      [3 , 2 , 1 , 1 , 0 , 1 , 1 , 2 , 2 , 2 , 3 , 4],
      [4 , 3 , 2 , 2 , 1 , 0 , 2 , 3 , 3 , 1 , 2 , 3],
      [4 , 3 , 2 , 2 , 1 , 2 , 0 , 1 , 3 , 1 , 2 , 3],
      [5 , 4 , 3 , 3 , 2 , 3 , 1 , 0,  4 , 2 , 1 , 2],
      [3 , 2,  1 , 3 , 2 , 3  ,3 , 4 , 0 , 4 , 5 , 6],
      [5 , 4 , 3 , 3 , 2 , 1 , 1 , 2 , 4 , 0 , 1 , 2],
      [6 , 5 , 4 , 4 , 3 , 2 , 2 , 1 , 5 , 1 , 0 , 1],
      [7 , 6 , 5 , 5 , 4 , 3 , 3  ,2 , 6 , 2 , 1 , 0]]

    v2 = [[0 , 3 , 4 , 6 , 8 , 5 , 6 , 6 , 5 , 1 , 4 , 6],
      [3 , 0 , 6 , 3 , 7 , 9 , 9 , 2 , 2 , 7 , 4 , 7],
      [4 , 6 , 0 , 2 , 6 , 4 , 4  ,4  ,2  ,6  ,3  ,6],
      [6 , 3 , 2 , 0 , 5 , 5 , 3 , 3 , 9 , 4 , 3 , 6],
      [8 , 7 , 6 , 5 , 0 , 4 , 3 , 4 , 5 , 7 , 6  ,7],
      [5 , 9 , 4 , 5 , 4 , 0 , 8 , 5 , 5 , 5 , 7 , 5],
      [6 , 9 , 4 , 3 , 3  ,8  ,0 , 6 , 8 , 4 , 6 , 7],
      [6 , 2 , 4 , 3 , 4 , 5  ,6  ,0  ,1  ,5  ,5 , 3],
      [5 , 2 , 2 , 9 , 5 , 5 , 8 , 1 , 0 , 4 , 5 , 2],
      [1 , 7 , 6 , 4 , 7 , 5 , 4 , 5 , 4 , 0 , 7 , 7],
      [4 , 4 , 3 , 3  ,6  ,7  ,6  ,5  ,5  ,7  ,0 , 9],
      [6 , 7 , 6 , 6 , 7 , 5 , 7 , 3 , 2 , 7 , 9 , 0]]
    answer = []
    cs = init(12)
    fitness1 = fitness(cs,12,v1,v2)
    evolution = 1200
    for i in range(evolution):
        
        cs,fitness1 = filter_max(cs,fitness1)
        cs =cross(cs,fitness1)
        fitness1 = fitness(cs,12,v1,v2)
        for i in range(100):
            cs = Mutation(cs,fitness1)

        print(min(fitness1))
        answer.append(min(fitness1))
    print("最小解为:",min(answer))
    plt.plot(answer)
    #print(cs)
    #print(fitness1)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值