博弈论及 SG函数

以下纯属个人理解,如有错误还请各位大佬指出

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

以下我提取最关键的点:

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

SG的值只有0,非0两种状态,非0(不管是几)都是一个状态。

后继状态:你取玩石子后的状态

两个博弈的要点:

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

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

1.设必败态为P, 必胜态为N;

2.若某状态的后继状态中存在P,则该状态为N,因为此时先手把必败态转移给对方;

3.若某状态的后继状态均为N,则该状态为P,此时自己必败;

4.sg函数由底向上构建,保证后面延续前面的状态;

5.若某状态为P,则其sg函数值为0(其后继状态中sg函数值均为非0,怎样都要把必胜态拱手相让),且两条件等价,若N态,则sg函数值对应为非0(非零证明前面的状态中存在0,即必败态)

6.为什么要定义mex{}运算?为了模拟第五条,如果之前均为非零即N态,则此状态sg值必为0(P态),那么N态时怎么赋值?假如某个状态后继状态sg函数值为{0,1,2,3,5,6,7},显然mex{} = 4,可以由当前状态变为后继状态中的任何一个状态{0,1,2,3,5,6,7},但是现在需要构建一个连续的段落,如果sg函数值等于7,并不能变成状态4,但是如果sg = 4,却可以变成之前的任意状态{0, 1, 2, 3},这样问题就变成该堆有四个石子!——nim博弈的规则!异或!

模板:

同一个游戏里面只要f[]没变,sg函数只要算一遍
int sg[1005];
int mex[1005];
void getsg(){  
    memset(sg,0,sizeof(sg));  //堆数为一时的sg函数
    for(int i=1;i<=1000;i++){
        memset(mex,0,sizeof(mex));
        for(int j=0;j<=9&&f[j]<=i;j++)
            mex[sg[i-f[j]]]=1;
        for(int j=0;;j++)
            if(!mex[j]){
                sg[i]=j;
                break;
            }
    }
}
一堆里面数量为n;
if(sg[n]) 先手赢

三堆时分别为m,n,p;
 if( (sg[m]^sg[n]^sg[p])) 即不为0时先手赢。

n堆时以此类推。 

 

 

以下修改自http://www.cnblogs.com/Mathics/p/3948482.html

尼姆游戏和尼姆博弈并不完全一样,尼姆博弈可以说是从尼姆游戏发展而来的

尼姆游戏(维基百科):

 

    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函数有用的状态只有0和非1,非0代表必胜态,表明你所有可选的方案中

  要注意到,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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值