zoukankan      html  css  js  c++  java
  • Nim游戏与SG函数 ——博弈论小结

     

      写这篇博客之前,花了许久时间来搞这个SG函数,倒是各路大神的论文看的多,却到底没几个看懂的。还好网上一些大牛博客还是性价比相当高的,多少理解了些,也自己通过做一些题加深了下了解。

     

    既然是博弈,经典的NIM游戏不得不提一下,这也是要不断提醒自己别忘了NIM游戏才是SG函数由来的核心关键!

      1. 若干堆石头。

      2. 甲和乙轮流从任意堆中取任意个石头。

      3. 谁不能取就输。

    分析:

      对于一个博弈来说,P-position表示previous,代表先手必败,即后手必胜,N-position表示next,代表先手必胜,后手必败。

      两个博弈的结论:

        若当前状态为N,至少存在下一个能达到的状态是P。(1)

        若当前状态为P,则所有下一个能达到的状态是N。(2)

      显然(0, 0, ..., 0)为必胜态N

    凭借这样,因此我们可以通过记忆化搜索可以搜出答案,但是时间复杂度是n!级别的。因此需要更高效的方法来解决NIM问题。

    》》》Bouton's Theorem

      对于一个Nim游戏的局面(a1, a2, ..., an),它是P-position当且仅当a1 xor a2 xor... xor an=0

    简要证明:

      显然(0, 0, ..., 0)为必败态。

      可归纳证明

      A)对于P-position局面(a1, a2, ..., an)满足a1 xor a2 xor... xor an=0,对于所有合法的移动,

          不妨设为新局面(a1-x, a2, ..., an),则

              (a1-x) xor a2 xor ... xor an

              =(a1-x) xor a2 xor ... xor an xor a1 xor a1

              =(a1-x) xor a1!=0(其中a1>x)。

          故满足结论(2)

      B)对于N-position局面满足a1 xor a2 xor... xor an=k!=0,则存在一个移动使得新局面(a1', a2', ..., an')有a1' xor a2' xor... xor an'=0。因为{ak}中存在ai的二进制在k的最高位上为1,否则k的最高位不能得到,将ai变为ai xor k(<ai),有 a1 xor a2 xor ... xor an xor ai xor k = 0。

          故满足结论(1)

      故若Nim游戏局面满足博弈的两个结论,故存在必胜/必败态及必胜态的必胜步骤。

    至此,Nim游戏得到基本解决。

    接下来才是重头菜!

      引入SG函数,SG(x)=mex{SG(y) | x->y },其实就是状态x能转移到y。

      SG是表示当前局面的状态(a1,a2,...,an)的一种状态(自然数集合)的函数。有点晕—。—

      mex(Y)表示非Y集合中最小的自然数。例如mex(0,2)=1,mex(1,3)=0。

      此前每次看到很多相关博客引入SG函数都很突兀,凭什么要这样定义mex(),还有SG到底是什么东西?而后都是好像以这两个为基础给出SG的性质,证明之类,看得也似懂非懂。我也不能十分保证我能够讲明白这个高深的理论,如果发现有错,欢迎大牛们指正!

      还是从Nim游戏引入一下这个SG,或者说SG的核心就是Nim游戏,先看看有什么作用。

      (如果发现看不太懂,回去看看SG的定义)

     只考虑一堆石头的情况,

       SG(0)=0(因为(0)没有后继,所以自然SG(0)=0)

       SG(1)=mex(SG(0)=0)=1

       SG(2)=mex(SG(0)=0,SG(1)=1)=2

       ...

       SG(n)=n

     当然一维Nim游戏比较特殊,才有SG(n)=n

     

     考虑两堆的话,

       SG(0,0)=0

       SG(1,0)=SG(0,1)=mex(SG(0,0)=0)=1

       SG(2,0)=SG(0,2)=mex(SG(0,0)=0,SG(1,0)=1)=2

       SG(1,1)=mex(SG(0,1)=1)=0  //开始有点感觉了吗?

       SG(2,1)=SG(1,2)=mex(SG(1,1)=0,SG(2,0)=2,SG(0,1)=1)=3

       ...

     从二维的数据上可以归纳出,SG(a,b)=a^b

     

     更多的,想必也能猜出来吧,其实就是之前讨论Nim游戏的结论,所以我才斗胆说SG核心来源于Nim,事实真相倒是不大清楚,相关中文资料确实少。

      想必现在应该有点感觉吧,SG的本质应该是将n维Nim游戏映射到1维Nim游戏。

      想想,每个n维状态对应的1维状态SG,则其状态就和1维相同,可以变为SG-1,SG-2,,,,,1,0,故先手每次都可以将其变成0,而这相当于这一次的1维Nim游戏胜利,而只要能把这个状态保持下去,那么最终就一定能够胜利,也就是说n维Nim游戏就赢了。

       此外异或这真是很神奇的运算。

    至此,Nim游戏的结论已经是毋庸置疑,而SG的含义也明白了,而SG的求法却有些模糊,为什么SG(x)=mex(SG(y) | x->y) ?

      要注意到,SG函数的应用远远不局限于Nim游戏,Nim游戏只是SG的一个根基吧?拓展出来的问题更是千变万化。

      我们先来看一个看似更为普遍的问题,实际上是Nim游戏的变性。

        对于有向无环图,一个起点处有一个棋子,两个人轮流移动棋子一步,谁先到达终点谁就胜利。

      我们依然套用SG函数模型(SG(x)=mex(SG(y) | x->y) )来看,(现在状态x就是棋子所在位置)

      SG函数应该满足一下两个条件:

        A)SG(x)为0当且仅当当前局面x为P-position

        B)SG(x)不为0当且仅当当前局面x为N-position

      要注意到SG函数是递归求出来的

      若单纯从该有向图博弈游戏来看,满足

        a)若SG(x)=b!=0,对于任意a∈N && a<b,均存在节点x能够达到的节点y满足SG(y)=a (从SG定义可知)

        b)若SG(x)=b,若x为终点,则当前局面为P-position

                若x非终点,则对于任意节点x能够到达的节点y满足SG(x)!=b

      因此只需递归算出起点的SG值,接着判断起点的SG是否为0,即可判断当前局面是N/P-position。

      可以看出,上述两点都是由SG函数的定义得到,这就是SG函数这样定义的直接原因!当然你可能还是不清楚这样定义的根本原因。

      对于该博弈游戏已经得到解决,但是如果是n个这样的博弈游戏合并起来呢?

        对于有向无环图,n个起点处有棋子,两个人轮流移动一个棋子一步,谁无法移动就失败。

      单单靠SG函数依然是可以计算出来的,但是你实际上还是只用到SG函数是否为0,而对于其SG非0的值的意义没有利用到。

      其实对比Nim游戏模型:

        a)若SG(x)=b,对于任意a∈N && a<b,均存在x能够达到的状态y满足SG(y)=a.

        b)若SG(x)=b,若状态x为(0, 0, ..., 0),则当前局面为P-position

                若状态x非(0, 0, ..., 0),则对于任意x能够达到的状态y,均有SG(y)!=b.

      可以发现上面两个游戏实际上是一致的。

      这样就能够套用Bouton's Theorem对有向图博弈游戏进行运算,即SG(a1,a2,...an)=SG(a1) xor SG(a2) xor ... xor SG(an) ,这才是SG函数如此定义的最终目的,让它能够转化为Nim游戏。

      从而这个博弈问题即可轻松通过n个棋子的SG值进行异或,求出整个游戏的SG值,判断是否为0即可。

      是不是一下子将一个复杂的问题得到大大的简化?

      接下来证明SG(x)在多个博弈游戏组合起来时的一个整体博弈游戏依然满足满足 a)& b):

      首先能转化成Nim游戏模型的游戏,其SG值满足:

        SG(a1,a2,...an)=SG(a1) xor SG(a2) xor ... xor SG(an) 

      在这个基础上,

        a)即证明x=(a1, a2, ..., an)=>y=(a1', a2', ..., an')下 有SG(y)=a (所有a∈N && a<b),取k=a xor b,显然存在SG(ai)的二进制在k的最高位上为1,取SG(ai’)=SG(ai) xor k,则SG(a1', a2', ... , an')=SG(a1) xor SG(a2) xor ... xor SG(an) xor k = a 。

        得证

        b) 若b)不成立,则对于任意x,均存在能够达到的状态y,有SG(y)=b,则有 SG(a1) xor SG(a2) xor ... xor SG(an) = 0 ,设状态y为(a1', a2, ..., an) 有 SG(a1') xor SG(a2) xor ... xor SG(an)=b ,由异或满足消去率,a1=a1',与SG定义矛盾。

        得证

      当然上述还需要数学归纳法来证明

      详细的证明参见 王晓珂《解析一类组合游戏》  

      小结:

        SG函数的真正目的是将复杂的博弈问题分解成一个个独立的博弈问题之后,通过SG函数将其转化为一个个Nim游戏,然后利用Bouton's Theorem求出整个博弈问题的解。这也就是Sprague-Grundy定理。SG函数的定义就是根据Nim游戏的性质构造出来的一个函数,可以将普通的博弈问题转化为Nim问题,而Nim问题一定有解,故相应博弈问题也一定有解。

    这些题目进行巩固以加深了解博弈论知识》》》博弈论相关题目

    除此之外,今后还将继续更新此文,扩充一些必要的拓展。

    推荐的几篇相关大牛博客(比起那些生涩的论文好太多):

      SG函数闲扯--ydc的日志

      博弈论(二):Sprague-Grundy 函数定理

    必读论文:

      王晓珂《解析一类组合游戏》 

       《GAME THEORY》——Thomas S. Ferguson

  • 相关阅读:
    LInux设备驱动分析—— kmalloc和kzalloc函数
    g++使用总结
    Redis那些事(一) — Redis简介
    C++后台知识点总结(一)
    秋招复习-C++(三)
    C++之类成员的访问权限详解(一)
    c++内联函数解析(inline)
    论文图片
    markdown Typora学习随笔
    ROS 导航设计随笔
  • 原文地址:https://www.cnblogs.com/Mathics/p/3948482.html
Copyright © 2011-2022 走看看