人工智能之遗传算法

遗传算法解决八皇后问题
遗传算法的主要思想:模拟自然界生物遗传进化的优胜劣汰的过程解决问题
算法的过程:1、根据具体的问题,生成初始种群,规定适应度函数。
2、判断种群中的个体是否满足终止条件,否则转3,是则转4。
3、对种群中的个体进行选择,交叉,变异,转2。
4、结束。
1、

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#遗传算法八皇后


import random
import numpy as np
from itertools import accumulate
from bisect import bisect_right
import copy as cp

global mutationtimes
mutationtimes=0
class eight_queen():
    def __init__(self):
        self.populations = []

    # 初始化种群(已改32)
    def init_populations(self):
        temp_populations = []
        for i in range(32):
            population = []
            for j in range(8):
                num = random.randint(0,7)
                population.append(num)
            temp_populations.append(population)
        self.populations = temp_populations
        print("初始种群个体情况:", self.populations)
#自主选择生成个体(已改32)
    def Selfselectioninput(self):
        temp_populations = []
        for i in range(32):
            population = []
            a=input()
            for j in range(8):
                num =int(a[j])
                population.append(num)
            temp_populations.append(population)
        self.populations = temp_populations
        print("初始种群个体情况:", self.populations)
    # 适应度函数
    def calu_fitness(self):
        fitness_list = []
        for c in range(0, 32):
            total = 28
            for i in range(0, 7):
                for n in range(i + 1, 8):
                    if self.populations[c][i] == self.populations[c][n]:
                        total -= 1
                    if self.populations[c][i] + n - i == self.populations[c][n] or self.populations[c][i] - n + i == self.populations[c][n]:
                        total -= 1
            fitness_list.append((c, total))
        return fitness_list

    # 选择#轮盘赌选择
    def roulettewheelselection(self, fitness_list):#根据适应度列表进行选择
        #适应度函数未修改(129)
        parent = []             #选择的结果作为父亲种群进行交叉和变异
        P = []
        p = 0
        fitness_list = sorted(fitness_list, key= lambda a:a[1], reverse=True)#对适应度列表排序,key为排序依据,倒序
        for m in range (0,32):
            p = p+fitness_list[m][1]
        for k in range (0,32):
            P.append(fitness_list[k][1]/p)
        Q= list(accumulate ([q for q in P ]))
        for i in range(0,32):
            parent_index = bisect_right(Q, random.random())  # bisect_right将随机产生的数字插入顺序序列Q中,并返回其索引值
            parent.append(cp.copy(self.populations[fitness_list[parent_index][0]]))#这里修改了
        self.populations=parent
        print("轮盘赌选择之后的个体:", self.populations)
		
    #排序选择
    def rankingselection(self, fitness_list):#根据适应度列表进行选择

        parent = []             #选择的结果作为父亲种群进行交叉和变异
        fitness_list = sorted(fitness_list, key= lambda a:a[1], reverse=True)#对适应度列表排序,key为排序依据,倒序
        p = []                                           # 排序后分配的概率列表
        P = []                                            #归一化后的概率
        pmin = 0.1
        pmax = 0.9
        p.append(pmin)
        for i in range(2, 32):
            p.append(pmin + (pmax - pmin) * (i - 1) / (32 - 1))
        p.append(pmax)

        for pi in p:                                #归一化
            P.append(pi / sum(p))
        Q=list(accumulate(q for q in P))
        for i in range(0,32):
            parent_index = bisect_right(Q, random.random())  # bisect_right将随机产生的数字插入顺序序列Q中,并返回其索引值
            parent.append(cp.copy(self.populations[fitness_list[parent_index][0]]))
        self.populations = parent
        print("排序选择之后个体情况:", self.populations)

    # 单点交叉
    def onepointcrossOver(self):

        for k in range(0,24):             #固定交叉概率75%
            flag = True
            while flag:
                individual1 = random.randint(0, 31)
                individual2 = random.randint(0, 31)
                cross_point = random.randint(0, 7)
                if individual1 != individual2 :
                    for i in range(cross_point , 8):
                        self.populations[individual1][i], self.populations[individual2][i] \
                            = self.populations[individual2][i], self.populations[individual1][i]
                    flag = False
                    print("本次交叉的个体是:",individual1, individual2)
        print("交叉之后的种群:",self.populations)

    #两点交叉
    def twopointcrossover(self):
        for K in range(0,24):             #固定交叉概率75%
            flag = True
            while flag:
                individual1 = random.randint(0, 31)
                individual2 = random.randint(0, 31)
                cross_point1 = random.randint(0, 7)
                cross_point2 = random.randint(0, 7)
                if cross_point1 > cross_point2:
                    t = cross_point1
                    cross_point1 = cross_point2
                    cross_point2 = t
                if individual1 != individual2 :
                    for i in range(cross_point1 + 1, cross_point2 + 1):
                        self.populations[individual1][i], self.populations[individual2][i] = self.populations[individual2][i], self.populations[individual1][i]
                    flag = False
                print("本次交叉的个体是:", individual1, individual2)
        print("交叉之后的种群:", self.populations)


    # 变异次数固定,随机变异位置、变异值
    def fixed_mutation(self):
        for i in range(0,8):
            m=random.randint(0, 31)
            mutation_point = random.randint(0, 7)
            mutation_number = random.randint(0, 7)
            self.populations[m][mutation_point]= mutation_number
            print("变异的个体为:{0}".format(m))
        fitness_list = eq.calu_fitness()
        print("变异之后的种群:",self.populations)

    #随机变异次数、变异位置、变异值
    def nofixed_mutation(self):
        mutation_count = random.randint(1, 31)
        for i in range(mutation_count):
            mutation_point = random.randint(0,7)
            mutation_number = random.randint(0,7)
            chromosome = random.randint(0,31)
            self.populations[chromosome][mutation_point] = mutation_number
            print("变异的个体为:{0}".format(chromosome))
        fitness_list = eq.calu_fitness()
        print("本次循环变异了{0}次".format(mutation_count))
        print("变异之后的种群:",self.populations)

 #判断
def sentence_fitness():
    n=False
    fitness_list = eq.calu_fitness()
    for i in fitness_list:
        if i[1] == 28:
            n = True
            print("I find it! The answer is {0}".format(eq.populations[i[0]]))
            print("I did {0} cycle to find it".format(count))
            print("I did {0} mutation to find it".format(mutationtimes))
            output = np.array([[0] * 8 for i in range(8)])
            for i, j in enumerate(eq.populations[i[0]]):
                output[i][j] = 1
            print(output)
    return n
if __name__ == "__main__":
    count = 1
    eq = eight_queen()
    print("本程序是遗传算法八皇后,包括选择、交叉、变异过程:")
    print("请选择生成初始种群的方法:1.随机生成 2.用户自主选择输入初始种群(输入八位0-7之间的数字,格式为“14725360”)")
    a1 = input()
    if a1 == '1':
        # 初始化种群
        eq.init_populations()
    else:
        ##自主选择生成个体
        eq.Selfselectioninput()
    #计算适应度函数
    fitness_list = eq.calu_fitness()
    print("初始种群的适应度:",fitness_list)

    #选择算法
    print("请选择初始种群的选择策略:1.轮盘赌方式 2.排序选择")
    b1 = input()
    if b1 == '1':
         # 轮盘赌函数
         eq.roulettewheelselection(fitness_list)
    else:
         ## 排序选择
         eq.rankingselection(fitness_list)

    print("请选择个体交叉算法:1.单点交叉 2.两点交叉")
    c1 = input()
    if c1 == '1':
        # 单点交叉
        eq.onepointcrossOver()
    else:
        # 两点交叉
        eq.twopointcrossover()
    mutationtimes+=1

    print("请选择个体变异算法:1.确定变异概率的实值变异 2.随机概率的实值变异")
    d1 = input()
    if d1 == '1':
        # 确定变异概率的实值变异
        eq.fixed_mutation()
    else:
        # 随机概率的实值变异
        eq.nofixed_mutation()

    while True:
        n = False
        count += 1
       #选择算法
        if b1 == '1':
             # 轮盘赌函数
             eq.roulettewheelselection(fitness_list)
             n=sentence_fitness()
             if n==True:
                 break
        else:
             ## 排序选择
             eq.rankingselection(fitness_list)
             n = sentence_fitness()
             if n == True:
                 break
        #交叉算法
        if c1 == '1':
            # 单点交叉
            eq.onepointcrossOver()
            n = sentence_fitness()
            if n == True:
                break
        else:
            # 两点交叉
            eq.twopointcrossover()
            n = sentence_fitness()
            if n == True:
                break

            #变异算法
        if d1 == '1':
            # 确定变异概率的实值变异
            eq.fixed_mutation()
            n = sentence_fitness()
            if n == True:
                break
        else:
            #  随机变异概率的实值变异
            eq.nofixed_mutation()
            n = sentence_fitness()
            if n == True:
                break
        mutationtimes += 1

2、

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#遗传算法八皇后

import random
import numpy as np
from itertools import accumulate
from bisect import bisect_right
import copy as cp
class eight_queen():
    def __init__(self):
        self.populations = []

    # 初始化种群       生成16个基因不相同的个体作为初始化种群
    def init_populations(self):
        temp_populations = []
        for i in range (16):
            population = random.sample(range(0,8),8)
            temp_populations.append(population)
        self.populations = temp_populations
        print(self.populations)

#自主选择生成个体
    def Selfselectioninput(self):
        temp_populations = []
        for i in range(16):
            population = []
            a=input()
            for j in range(8):
                num =int(a[j])
                population.append(num)

            temp_populations.append(population)
            print(temp_populations)
        self.populations = temp_populations

    # 适应度函数           互不攻击的皇后的个数作为适应度函数
    def calu_fitness(self):
        fitness_list = []
        for c in range(0, 16):
            total = 28
            for i in range(0, 7):
                for n in range(i + 1, 8):
                    if self.populations[c][i] == self.populations[c][n]:
                        total -= 1
                    if self.populations[c][i] + n - i == self.populations[c][n] or self.populations[c][i] - n + i == self.populations[c][n]:
                        total -= 1
            fitness_list.append((c, total))
        return fitness_list

    # 轮盘赌选择
    def roulettewheelselection(self, fitness_list):#根据适应度列表进行选择
        parent = []             #选择的结果作为父亲种群进行交叉和变异
        P = []
        p = 0
        fitness_list = sorted(fitness_list, key= lambda a:a[1], reverse=True)#对适应度列表排序,key为排序依据,倒序
        for m in range (0,16):
            p = p+fitness_list[m][1]
        for k in range (0,16):
            P.append(fitness_list[k][1]/p)
        Q= list(accumulate ([q for q in P ]))
        for i in range(0,16):
            parent_index = bisect_right(Q, random.random())  # bisect_right将随机产生的数字插入顺序序列Q中,并返回其索引值
            parent.append(cp.copy(self.populations[fitness_list[parent_index][0]]))#这里修改了
        self.populations=parent
        print("选择操作之后:")
        print(self.populations)
		
		
    #排序选择
    def rankingselection(self, fitness_list):#根据适应度列表进行选择

        parent = []             #选择的结果作为父亲种群进行交叉和变异
        fitness_list = sorted(fitness_list, key= lambda a:a[1], reverse=True)#对适应度列表排序,key为排序依据,倒序
        p = []                                           # 排序后分配的概率列表
        P = []                                            #归一化后的概率
        pmin = 0.1
        pmax = 0.9
        p.append(pmin)
        for i in range(2, 16):
            p.append(pmin + (pmax - pmin) * (i - 1) / (16 - 1))
        p.append(pmax)
        for pi in p:                                #归一化
            P.append(pi / sum(p))
        Q=list(accumulate(q for q in P))
        for i in range(0,16):
            parent_index = bisect_right(Q, random.random())  # bisect_right将随机产生的数字插入顺序序列Q中,并返回其索引值
            parent.append(cp.copy(self.populations[fitness_list[parent_index][0]]))
        self.populations = parent
        print("选择操作之后:")
        print(self.populations)

    # 次序交叉        交叉依然保证个体的基因不相同
    def order_crossOver(self):
        for k in range (0,13):                       #75%是个大概数,实际上低于75%
            offspring1 = [9 for _ in range(8)];offspring2 = [9 for _ in range(8)]
            parent1 = [];parent2 = [];list1 = [];list2 = []
            individual1 = random.randint(0,15);individual2 = random.randint(0,15)#交叉个体
            parent1 = self.populations[individual1];parent2 = self.populations[individual2]
            cross_point1 = random.randint(0,7);cross_point2 = random.randint(0,7)#交叉点
            print("本次交叉的个体是:",individual1,individual2)
            if cross_point1 > cross_point2:
                t=cross_point1;cross_point1=cross_point2;cross_point2=t
            for i in range (cross_point1,cross_point2+1):
                list1.append(parent1[i])
                offspring1[i]=parent1[i]
                list2.append(parent2[i])
                offspring2[i]=parent2[i]
            for m in range(8):                       #这里选择parent2 中不在list1中的基因依次插入到protochild1中
                for n in range (8):
                    if parent2[m] not in list1 and offspring1[n]==9:
                        offspring1[n] = parent2[m]
                        break
            for p in range (8):                      #同上,选择parent1中不在list2 中的基因依次插入到protochild2中
                for q in range (8):
                    if parent1[p] not in list2 and offspring2[q]==9:
                        offspring2[q] = parent1[p]
                        break
            self.populations[individual1],self.populations[individual2]=\
                offspring1,offspring2
        print('次序交叉之后:')
        print(self.populations)


      #子路径替换交叉                       交叉后依然保持每个个体的基因的多样性
    def subtour_exchange_crossover(self):
        for n in range (0,13):
            c=0
            offspring1 = [];offspring2 = [];list1 = [];list2 = []
            individual1 = random.randint(0,15);individual2 = random.randint(0,15)
            crosspoint1 = random.randint(0,7);crosspoint2 = random.randint(0,7)
            print("本次交叉的个体是:", individual1, individual2)
            offspring1 = self.populations[individual1];offspring2=self.populations[individual2]#先在种群中选择两个子代
            if crosspoint1 > crosspoint2:
                t = crosspoint1; crosspoint1 = crosspoint2; crosspoint2 = t
            for i in range (crosspoint1,crosspoint2+1):    #将选择的要交叉的部分基因放入列表中
                list1.append(offspring1[i])
            for j in range (crosspoint1,crosspoint2+1):
                for m in range (c,8):
                    if offspring2[m] in list1:#改变子代中的基因
                     #如果子代2的基因在列表中,则把这个基因换到子代一的选择的交叉的位置
                        offspring1[j],offspring2[m]=offspring2[m],offspring1[j]
                        c = m+1
                        break
            self.populations[individual1], self.populations[individual2] = \
                offspring1, offspring2
        print('子路径替换交叉之后:')
        print(self.populations)

    # 交换变异
    def exchange_mutation(self):
        for i in range(0,2):
            n = random.randint(0, 15)

            mutation_point1 = random.randint(0, 7)
            mutation_point2 = random.randint(0, 7)
            print("本次变异的个体是:", n)
            print("本次变异的变异点是:", mutation_point1,mutation_point2)
            self.populations[n][mutation_point1], self.populations[n][mutation_point2] = \
                self.populations[n][mutation_point2], self.populations[n][mutation_point1]
        print("交换变异之后:")
        print(self.populations)


    #替换变异
    def displacement_mutation(self):
        for j in range (0,2):
            s = random.randint(0,15)
            n = random.randint(0,7)
            m = random.randint(0,7)

            k = random.randint(0,7)
            print("本次变异的个体是:", s)

            if n >= m:
                t = n;n = m;m = t
            print("本次变异的变异点是:", n, m)
            for i in range (n,m+1):
                d = self.populations[s].pop(i)
                self.populations[s].insert(k,d)
                k += 1
        print('替换变异之后:')
        print(self.populations)




 #判断
def sentence_fitness():
    n=False
    fitness_list = eq.calu_fitness()
    for i in fitness_list:
        if i[1] == 28:
            n = True
            print("I find it! The answer is {0}".format(eq.populations[i[0]]))
            print("I did {0} cycle to find it".format(count))
            output = np.array([[0] * 8 for i in range(8)])
            for i, j in enumerate(eq.populations[i[0]]):
                output[i][j] = 1
            print(output)
    return n
if __name__ == "__main__":
    #s_time = time.time()n
    count = 1
    eq = eight_queen()
    print("本程序是遗传算法八皇后,包括选择、交叉、变异过程:")
    print("请选择生成初始种群的方法:1.随机生成 2.用户自主选择输入初始种群(输入八位不相同的0-7之间的数字,格式为“14725360”)")

    a1 = input()
    if a1 == '1':
        # 初始化种群
        eq.init_populations()
    else:
        ##自主选择生成个体
        eq.Selfselectioninput()
    #计算适应度函数
    fitness_list = eq.calu_fitness()
    print(fitness_list)

    #选择算法
    print("请选择初始种群的选择策略:1.轮盘赌方式 2.排序选择")
    b1 = input()
    if b1 == '1':
         # 轮盘赌函数
         eq.roulettewheelselection(fitness_list)
    else:
         ## 排序选择
         eq.rankingselection(fitness_list)

    print("请选择个体交叉算法:1.顺序交叉 2.子路径交换交叉")
    c1 = input()
    if c1 == '1':
        eq.order_crossOver()#顺序交叉
    else:
        eq.subtour_exchange_crossover()#子路径交换交叉


    print("请选择个体变异算法:1.交换变异 2.替换变异")
    d1 = input()
    if d1 == '1':
        # 交换变异
        eq.exchange_mutation()
    else:
        # 替换变异
        eq.displacement_mutation()

    while True:
        n = False
        count += 1
       #选择算法
        if b1 == '1':
             # 轮盘赌函数
             eq.roulettewheelselection(fitness_list)
             n=sentence_fitness()
             if n==True:
                 break
        else:
             ## 排序选择
             eq.rankingselection(fitness_list)
             n = sentence_fitness()
             if n == True:
                 break
        #交叉算法
        if c1 == '1':
            # 次序交叉
            eq.order_crossOver()
            n = sentence_fitness()
            if n == True:
                break
        else:
            # 子路径
            eq.subtour_exchange_crossover()
            n = sentence_fitness()
            if n == True:
                break

            #变异算法
        if d1 == '1':
            # 交换变异
            eq.exchange_mutation()
            n = sentence_fitness()
            if n == True:
                break
        else:
            # 替换变异
            eq.displacement_mutation()
            n = sentence_fitness()
            if n == True:
                break

一、1和2 的区别是初始种群中2保持个体的基因不相同,2的交叉变异同时保持了这种基因的不同,程序的效率提高了百倍不止。
二、遗传算法在解决局部最优的问题时可以:
1、增大变异率(但不能超过50%,不然则会丧失遗传算法的优越性,变为随机搜索),增大交叉率,增大种群的数目。
2、拉伸选择时的概率。
3、自适应交叉概率,自适应变异概率(让变异和交叉的概率根据适应度进行改变,优秀的个体有较小的概率,性能比较差的个体有较大的概率)
4、模拟退火法。(需要继续看)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值