Python遗传算法部分匹配交叉(PMX)

问题描述

在进化算法的交叉环节中,无论是一点交叉还是两点交叉,基因重组后产生的后代可能出现编码重复的情况,那么就需要我们对产生的子代进行修订,常见修订算法有部分匹配交叉(PMX),顺序交叉(OX),循环交叉(CX)等

部分匹配交叉步骤(单点交叉为例)

step1: 确定初始种群
list1: [9, 3, 5, 4, 6, 0, 2, 1, 7, 8]
list2: [1, 4, 0, 2, 7, 8, 6, 9, 5, 3]

step2: 随机产生小于父代向量长度的数,如y=2
[9, 3] [5, 4, 6, 0, 2, 1, 7, 8]
[1, 4] [0, 2, 7, 8, 6, 9, 5, 3]

step3: 互换交换片段
[9, 3] [0, 2, 7, 8, 6, 9, 5, 3]
[1, 4] [5, 4, 6, 0, 2, 1, 7, 8]

step4: 修订
保持被交换的片段不动,在没有交换的片段中寻找重复值,然后在父代被换走的部分中找到对应位置的元素进行替换。
说起来比较模糊,举例说明
本例中[9,3]均与换过来的[0, 2, 7, 8, 6, 9, 5, 3]有重复元素。
我们找到[5, 4, 6, 0, 2, 1, 7, 8]中与9,3对应位置的元素,然后[9,3]中的元素对应替换
在这里插入图片描述
第一次交换后的片段由[9, 3]变为了[1, 8]。但是8也与交叉片段重复,依次执行本操作,将8->0,继续查重,发现还重复,然后0->5->7->6->2->4
最终的片段为[1, 4]
相同原理对第二个子染色体进行修订
最终的染色体为
[1, 4, 0, 2, 7, 8, 6, 9, 5, 3]
[9, 3, 5, 4, 6, 0, 2, 1, 7, 8]

代码

###########整数修正############
import random
import copy

a1 = random.sample(range(10), 10)
a2 = random.sample(range(10), 10)
# a1 = [4, 0, 8, 5, 9, 1, 7, 2, 6, 3]
# a2 = [4, 7, 3, 1, 6, 8, 5, 0, 2, 9]
a1_1 = copy.deepcopy(a1)
a2_1 = copy.deepcopy(a2)
print('初始种群为:\n', a1_1, '\n', a2_1)
# 交叉位置
y = random.randint(0,len(a1_1))
# 记录交叉项
fragment1 = a1[y:]
fragment2 = a2[y:]
print('--' * 20, '\n单点交叉交换元素为:\n{}{}\n{}{}'.format(a1_1[:y], fragment1, a2_1[:y], fragment2))
a1_1[y:], a2_1[y:] = a2_1[y:], a1_1[y:]
print('--' * 20, '\n{}位置以后元素实现单点交叉:\n{}{}\n{}{}'.format(y - 1, a1_1[:y], fragment2, a2_1[:y], fragment1))
a1_2 = []
a2_2 = []
for i in a1_1[:y]:
    while i in fragment2:
        i = fragment1[fragment2.index(i)]
    a1_2.append(i)
for i in a2_1[:y]:
    while i in fragment1:
        i = fragment2[fragment1.index(i)]
    a2_2.append(i)

child1 = a1_2 + fragment2
child2 = a2_2 + fragment1
print('--' * 20)
print('修正后的子代为:\n{}\n{}'.format(child1, child2))

运行结果

在这里插入图片描述

同理我们可以写出两点交叉变异的修订

import random
import copy

# random.seed(10)
# a1 = random.sample(range(1, 11), 10)
# a2 = random.sample(range(1, 11), 10)
def two_points_cross(a1,a2):
    # 不改变原始数据进行操作
    a1_1 = copy.deepcopy(a1)
    a2_1 = copy.deepcopy(a2)
    # 交叉位置,point1<point2
    point1 = random.randint(0, len(a1_1))
    point2 = random.randint(0., len(a1_1))
    while point1 > point2 or point1 == point2:
        point1 = random.randint(0, len(a1_1))
        point2 = random.randint(0., len(a1_1))
    # 记录交叉项
    fragment1 = a1[point1:point2]
    fragment2 = a2[point1:point2]
    # 交叉
    a1_1[point1:point2], a2_1[point1:point2] = a2_1[point1:point2], a1_1[point1:point2]
    # 定义容器
    a1_2 = []  # 储存修正后的head
    a2_2 = []
    a1_3 = []  # 修正后的tail
    a2_3 = []
    # 子代1头部修正
    for i in a1_1[:point1]:
        while i in fragment2:
            i = fragment1[fragment2.index(i)]
        a1_2.append(i)
    # 子代2尾部修正
    for i in a1_1[point2:]:
        while i in fragment2:
            i = fragment1[fragment2.index(i)]
        a1_3.append(i)
    # 子代2头部修订
    for i in a2_1[:point1]:
        while i in fragment1:
            i = fragment2[fragment1.index(i)]
        a2_2.append(i)
    # 子代2尾部修订
    for i in a2_1[point2:]:
        while i in fragment1:
            i = fragment2[fragment1.index(i)]
        a2_3.append(i)

    child1 = a1_2 + fragment2 + a1_3
    child2 = a2_2 + fragment1 + a2_3
    # print('修正后的子代为:\n{}\n{}'.format(child1, child2))
    return child1,child2

  • 18
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
用于制作游戏人物模型的由日本开发的MMD模型制作软件(已汉化) PmxEditor是用来给MMD的模型进行绑骨和物理演算的软件,因为这个都是日文,很多人看这个可能会有些茫然,很难辨认,不过这并没有很大的问题,我们只需要了解其中的一部分选项有什么功能,就可以来进行简单的绑骨了   1、打开PE,其中左边的“选尺”是用来选择要编辑的物体类型(按顺序看就是:顶点,面,骨骼,刚体,链接体);   “表”是用来调整背景颜色,顶点颜色一类的,在某些时候可以方便我们观察模型,进行一些细致的操作 ;   2、“绞”经常需要用,主要是用来确定模型需要编辑的范围   3、选择到材质这一项,就可以选择特定的部件用来单独编辑   4、选择材质0是白色馒头型物体,材质4是卷毛君的一个红晕,像这样,分别选用不同的材质,就可以分别编辑不同的区域了   5、如果有需要删除的部分,也可以使用这个面板,比如说,卷毛君的材质6是头上那根毛   6、勾选材质6,卷毛变黑了,点击这个“选尺材质の什么削除”   7、选择“是”,确认消除   8、卷毛的毛就拔掉了=   9、关于那个“涂”,则是用来刷权重用的   所谓刷权重,就是将骨骼与模型的顶点建立联系,让模型可以跟随骨骼来移动,也就是我们通常所说的绑骨   10、当然,PmxEditor的功能远不止这些,其它用得比较少的控件也有很多,大家可以在网上自行学习

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值