[python3]稳定匹配算法实现和优化

问题的描述

在这里就不赘述了,你能搜到这篇文章,那肯定知道只算法的背景是啥

解决思路

  1. 男生向还未拒绝其的女生中选出优先级最高的,并向其求婚
  2. 女生如果没有已经被优先级更高的男生求婚,则答应(女生以后可以反悔)。 如果反之,则拒绝
  3. 对此步骤进行loop,直到没有求婚发生

这篇文章,讲一个自己实现的GS算法的版本

看过一些博文,比如这篇文章 https://blog.csdn.net/lonfee88/article/details/6678190

文章使用的代码

上面那篇文章使用的代码是这样的,很清晰。

def find_stable_matching(man_preferences, woman_preferences):
    """
    Gale-Shapely Algorithm
    :param man_preferences:
    :param woman_preferences:
    :return:
    """

    length = len(man_preferences)
    is_man_free = [True] * length
    is_woman_free = [True] * length
    isManProposed = [[False for i in range(length)] for j in range(length)]
    match = [(-1, -1)] * length

    while True in is_man_free:
        indexM = is_man_free.index(True)
        if False in isManProposed[indexM]:
            indexW = -1
            for i in range(length):
                w = man_preferences[indexM][i]
                if isManProposed[indexM][w] is False:
                    indexW = w
                    break
            isManProposed[indexM][indexW] = True

            if is_woman_free[indexW] is True:
                is_woman_free[indexW] = False
                is_man_free[indexM] = False
                match[indexM] = (indexM, indexW)
            else:
                indexM1 = -1
                for j in range(length):
                    if match[j][1] == indexW:
                        indexM1 = j
                        break

                if woman_preferences[indexW].index(indexM) < woman_preferences[indexW].index(indexM1):
                    is_man_free[indexM1] = True
                    is_man_free[indexM] = False
                    match[indexM] = (indexM, indexW)
    print(match)
    return match

这个算法没问题, 结果也是对的。 但是我认为有点拖沓, 还可以进行精简。

我们输入 这样两个二维矩阵

    MP = [[1, 4, 3, 6, 2, 5, 8, 7, 9, 0],
          [2, 1, 0, 3, 4, 8, 5, 9, 7, 6],
          [4, 3, 8, 9, 0, 2, 1, 7, 6, 5],
          [2, 7, 6, 1, 4, 3, 8, 0, 9, 5],
          [5, 3, 8, 4, 2, 0, 7, 6, 1, 9],
          [5, 0, 1, 7, 2, 8, 9, 4, 6, 3],
          [6, 2, 9, 8, 0, 7, 5, 1, 4, 3],
          [9, 7, 1, 8, 0, 2, 5, 6, 3, 4],
          [8, 0, 5, 9, 6, 7, 1, 2, 4, 3],
          [7, 9, 1, 6, 2, 0, 5, 8, 4, 3]]

    WP = [[3, 5, 0, 6, 9, 4, 8, 7, 2, 1],
          [0, 1, 3, 2, 7, 8, 5, 9, 4, 6],
          [1, 0, 7, 9, 3, 2, 5, 8, 6, 4],
          [2, 0, 6, 3, 4, 1, 5, 7, 9, 8],
          [5, 6, 8, 3, 2, 0, 9, 4, 1, 7],
          [3, 0, 1, 7, 9, 8, 2, 4, 6, 5],
          [6, 2, 7, 8, 0, 9, 4, 1, 5, 3],
          [9, 3, 1, 2, 0, 7, 5, 6, 8, 4],
          [4, 1, 5, 9, 6, 7, 0, 2, 8, 3],
          [6, 0, 1, 7, 2, 9, 5, 8, 4, 3]]

上面的算法的结果是这样

[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 0), (6, 6), (7, 9), (8, 8), (9, 7)]

# 也就是0号男生配1号女生,以此类推。 说实话 我觉得结果甚至都有些重复。

我的版本


# 把自己带入 非成勿扰 录制现场
def gs_matching(man_preferences, woman_preferences):
    length = len(man_preferences)
    is_man_dated = [False] * length # 10位男嘉宾是否已经撩到妹妹了
    is_woman_dated = [False] * length # 10位美人是否已经名花有主
    result = [-1] * length

    while False in is_man_dated:
        new_man = is_man_dated.index(False)
        girls_he_likes = man_preferences[new_man] # 康康这个男生最喜欢谁
        for girl in girls_he_likes: 
        	# 查看女生是否已经被约
            if is_woman_dated[girl] is False: #发现没有,那就当场拿下
                result[new_man] = girl
                is_woman_dated[girl] = True
                is_man_dated[new_man] = True
                break # 换下一个男嘉宾登场,进行选择
            else:
            	# 女嘉宾已经心有所属,现在进入权利反转环节, 女生对两位男嘉宾进行挑选
                current_boyfriend = result.index(girl)
                if woman_preferences[girl].index(current_boyfriend) > woman_preferences[girl].index(new_man):
                	# 看看是不是更喜欢 新来的这个小鲜肉,如果是,果断甩掉之前的蓝朋友
                    is_man_dated[current_boyfriend] = False
                    result[current_boyfriend] = -1
                    is_man_dated[new_man] = True
                    result[new_man] = girl
                    break # 换下一个男嘉宾登场,进行选择
    print(result)

我的这个算法的结果是这样的

[1, 2, 3, 4, 5, 0, 6, 9, 8, 7]
# 结果数据的index虽然没显示出来,但是也代表意义。
# 结果数组的第0号位置,就代表0号男生配对1号女生, 以此类推。

区别

首先说,两个代码都可以正确的运行,获得稳定匹配的结果。
但是我的代码使用更小,更少的变量。
更少的数据交换。
也更符合“延迟接受”算法的含义。

posted @ 2020-06-24 14:23  Sight-Tech  阅读(341)  评论(0编辑  收藏  举报