面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?

640?wx_fmt=gif

2018 AI 开发者大会是一场由中美人工智能技术高手联袂打造的 AI 技术与产业的年度盛会!这里有 15+ 硅谷实力讲师团、80+AI 领军企业技术核心人物、100+ 技术&大众实力媒体、1500+AI 专业开发者——我们只讲技术,拒绝空谈!

面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?_第1张图片

参加 2018 AI 开发者大会,请点击 ↑↑↑


面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?_第2张图片

作者 | 木木

责编 | 郭芮

秋天到了,又是吃螃蟹的季节。白富美学姐前两天约我吃最爱的大闸蟹,席间向来开心的她却显得心事重重。

“你肿么啦?”我仔细地掰开蟹壳,问道。

“十一假期好多朋友办婚礼,可我男票一点要求婚的意思都没有,我都想考虑备胎了。”

“你自己和他说嘛!”我放下了金黄的大闸蟹。

“我可是个妹子,这样多不好。”学姐叹了口气。

看着学姐犹犹豫豫的样子就知道她需要鼓励了。我眉头一皱,计上心来:学姐呀,我来给你讲个故事。

前排提示:本文生动地讨论了稳定匹配问题盖尔沙普利算法的Python实现,该算法是稳定匹配模型的著名解法。


640?wx_fmt=png

写在前面


有一座城市,当地风俗是:想结婚的男子必须先向心仪的女子求婚,而女子则需要等待求婚。

牧师每年会邀请人数相同的适婚男女参与一次集体相亲。一次相亲活动可能有很多轮,男子会首先向自己最爱的女子求婚,女子则会在所有的追求者中选择她的最爱;如果男子被拒绝,下一轮会向他第二喜欢的女子求婚;上一轮已经订婚的女子如果得到她更爱的人的求婚,则会毫不留情地抛弃未婚夫,和更爱的人在一起。被抛弃的男子需要重新参与求婚。

如此反复,等大家都订婚,就举办集体婚礼。

假设:

参加求婚的男女数量保持一致;

每个男子都按喜爱程度对女子进行排序,比如最爱a,其次爱b,再次爱c;

每个女子也同样给每个男子排序。

面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?_第3张图片

此方法名为Gale-Shapley算法。优点如下:

1. 总有大家都订了婚的一天,不可能无限循环;

2. 中止后所有的婚姻是稳定婚姻。

所谓不稳定婚姻,比如有两对夫妇M1&F1和M2&F2, M1的老婆是F1,但他更爱F2;而F2的老公虽说是M2,但她更爱M1——这样的婚姻就是不稳定婚姻。有兴趣的读者可以自行搜索证明过程。

学姐的眼睛开始放光了:

坐在家里等求婚,下辈子请让我生在这个城市吧!

我神秘一笑:

是不是女孩子的天堂,让我们用Python来看一看最后的匹配满意度吧!


640?wx_fmt=png

样本生成


为了完成模拟过程,我们首先需要一些样本,即随机生成数量相等(可设置数量)的男性和女性,同时生成他们对每个异性个体的喜爱排名。

#设置男女生喜好样本
print('==============================生成样本数据==============================')
man = pd.DataFrame( [['w'+str(i) for i in random.sample(range(1,women_num+1),women_num)] 
                      for i in range(man_num)],
                    index = ['m'+str(i) for i in range(1,man_num+1)],
                    columns = ['level'+str(i) for i in range(1,women_num+1)]
                    )

women = pd.DataFrame( [['m'+str(i) for i in random.sample(range(1,man_num+1),man_num)] 
                      for i in range(women_num)],
                    index = ['w'+str(i) for i in range(1,women_num+1)],
                    columns = ['level'+str(i) for i in range(1,man_num+1)]
                    )
return (man,women)

640?wx_fmt=png

模拟男性求婚和女性接受订婚的过程


每天上午,每位还没订婚的男子会向还没拒绝过他的女子中他最爱的那一个求婚。

print('==============================测试集{}模拟开始=============================='.format(i))
print('==============================开始模拟求婚过程==============================')
level_num = 0
while man_ismapping['love_level'].min() == 0:
    level_num += 1
    print('==============================开始第{}天婚姻配对=============================='.format(level_num))
    u_mapping_man = man_ismapping[man_ismapping.target == 'n'].index.tolist()

    if level_num < 2:
        level_col = 'level' + str(level_num)
        man_choose = man[man.index.isin(u_mapping_man)][level_col].to_frame().reset_index()
        man_choose.columns = ['man_id''women_id']
        man_choose['range'] = 1
    else:
        m_id = u_mapping_man
        l = []
        for man_id in m_id:
            col_n = int(man_ismapping[man_ismapping.index == man_id].range[0])
            level_col = 'level' + str(col_n + 1)
            women_id = man[man.index == man_id][level_col][0]
            rg = col_n + 1
            l.append([man_id, women_id, rg])
        man_choose = pd.DataFrame(l, columns=['man_id''women_id''range'])

每天下午,每位女性会在自己接到的求婚信中,选择她最中意的男子接受求婚;如果没接到求婚,就继续等待。

for r in range(0, len(man_choose)):
    relationship = man_choose[man_choose.index == r]
    m = [i for i in relationship['man_id']][0]
    w = [i for i in relationship['women_id']][0]
    find = women[women.index == w].unstack().reset_index()
    find.columns = ['level''women_id''man_id']
    find = int([i for i in find[find['man_id'] == m]['level']][0].split('level')[1])
    o_love_level = [i for i in women_ismapping[women_ismapping.index == w]['love_level']][0]
    rg = [i for i in relationship['range']][0]
    if o_love_level == 0:
        women_ismapping.loc[w, 'love_level'] = find
        women_ismapping.loc[w, 'target'] = m
        women_ismapping.loc[w, 'range'] = level_num
        man_ismapping.loc[m, 'love_level'] = rg
        man_ismapping.loc[m, 'target'] = w
        man_ismapping.loc[m, 'range'] = rg
    elif o_love_level > find:
        m_o = women_ismapping.loc[w, 'target']
        man_ismapping.loc[m_o, 'love_level'] = 0
        man_ismapping.loc[m_o, 'target'] = 'n'
        man_ismapping.loc[m, 'love_level'] = rg
        man_ismapping.loc[m, 'target'] = w
        man_ismapping.loc[m, 'range'] = rg
        women_ismapping.loc[w, 'love_level'] = find
        women_ismapping.loc[w, 'target'] = m
        women_ismapping.loc[w, 'range'] = level_num
    else:
        man_ismapping.loc[m, 'range'] = rg
        pass


640?wx_fmt=png

运行代码并导出结果


面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?_第4张图片

学姐看着正在运行模拟过程有点着急了,我抽取其中一轮的结果先展示给她看:

面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?_第5张图片

纵轴代表该次模拟结果中,某位男性/女性的伴侣喜爱排名,即:匹配到的伴侣是他/她第X喜欢的异性。

显然,男性匹配到的伴侣离自己的最爱比女性更近——不止一点点!这可和“妹子天堂”的预期有点远啊!

学姐陷入了困惑:明明女性才掌握着订婚的决定权,而且男性即使暂时订婚成功,也有被抛弃的可能啊!你看,随着匹配轮次增加,男性的伴侣总是从自己最喜欢的对象慢慢变成不那么喜欢的对象;而女性伴侣却在一步步变好。你这个会不会是偶然啊!

我:是不是偶然,让我们来看看100次模拟中,男性/女性匹配到的伴侣喜爱排名均值分布吧。

面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?_第6张图片

纵轴代表其中一次模拟中,男性/女性的平均伴侣喜爱排名均值,即:匹配到的伴侣是他们/她们第X喜欢的异性。

可以明显看到,男性最终匹配到的伴侣的喜爱排名普遍高于女性

学姐终于收起了质疑:原来主动出击真有这么大的作用!为什么呀?

我分析道:学姐你看,女孩只能坐在家里等求婚,她喜欢的人可能连看到她的机会都没有。而男性在主动做出选择之时,每次都能选择自己最喜欢的对象。即使被拒绝,他的下一次求婚,也能送给可能接受他的、他最爱的女孩儿。这个游戏保证男孩的伴侣是可能和他在一起的最好的那一个,但对女孩就不是。

面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?_第7张图片

学姐:你说得对。面对自己喜欢的人,我应该去争取,而不只是等待。

我:这就对啦!世界上有什么事不需要努力呢?你有喜欢的人,就要好好努力,提升自己,去吸引ta,爱ta。

而提升自己有什么不错的渠道呢?Enmm,Python数据分析师了解一下?

作者:城市数据团木木,可能是全世界最帅的情感话题数据分析师。

声明:本文为作者投稿,版权归其个人所有。


面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?_第8张图片


征稿啦

CSDN 公众号秉持着「与千万技术人共成长」理念,不仅以「极客头条」、「畅言」栏目在第一时间以技术人的独特视角描述技术人关心的行业焦点事件,更有「技术头条」专栏,深度解读行业内的热门技术与场景应用,让所有的开发者紧跟技术潮流,保持警醒的技术嗅觉,对行业趋势、技术有更为全面的认知。

如果你有优质的文章,或是行业热点事件、技术趋势的真知灼见,或是深度的应用实践、场景方案等的新见解,欢迎联系 CSDN 投稿,联系方式:微信(guorui_1118,请备注投稿+姓名+公司职位),邮箱([email protected])。

推荐阅读:

  • 95 后程序员一出校门就拿年薪 32 万?

  • PHP 5 将于年底停止更新,六成用户将面临安全风险

  • “汉堡+奶昔”怎么就成了精致生活的热门标签?

  • EOS超级节点选举竟被恶意操控?那21个节点的背后踩着多少森森白骨

  • 程序员保命指南:专治无规范代码!

  • 程序员四大焦虑瞬间:拿什么拯救你,我日益后退的发际线?

  • 程序员:路人甲帮我找到月薪3万的工作!

面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?_第9张图片

640?wx_fmt=gif

你可能感兴趣的:(面对木讷的程序员小哥哥,我是该坐等对方开窍求婚还是主动出击?)