如果具有无限的处理能力,那么是否存在可以完美下象棋的算法?


29

是否存在这样一种算法,如果赋予它无限的处理能力,计算机可以完美下象棋,从而永远不会丢失?

如果是这样,我在哪里可以找到伪代码?


8
完美的国际象棋是什么意思?
赫尔·沃尔夫

5
@HerbWolfe我认为他的意思是,它绝不会做出让其对手强迫其输掉的举动,并且只有在所有可能的动作都允许其对手迫使其输掉的情况下才辞职。
David Schwartz

5
@DavidSchwartz-当然,“完美象棋”是无法定义的。“无限的处理能力”也不能。这是否意味着“在0时间内执行所有指令序列”?“有无数个可用的处理器”吗?FWIW-我对“完美的国际象棋”的定义是“永不输掉比赛”。
鲍勃·贾维斯

24
是的,这叫做蛮力。拥有无限的处理能力,尽管您可能还需要大量存储空间来保存搜索树,但您无需进行alpha-beta修剪。
迈克尔(Michael)

4
“算法”的概念和无限处理能力的概念并没有真正融合在一起。算法和可计算性理论都是基于在有限数量的步骤中获得结果的假设。如果允许执行无数个步骤,那么可计算与不可计算之间的区别就会消失。
迈克尔·凯

Answers:


62

是否存在算法?是。根据Zermelo的定理,有限确定性的完美信息两人游戏(如国际象棋)有三种可能性:第一个玩家有获胜策略,或者第二个玩家有获胜策略,或者任一玩家都可以平局。我们(尚)不知道这是国际象棋。(另一方面,跳棋已经解决:任何一方都可以强制平局。)

从概念上讲,该算法非常简单:构建完整的游戏树,分析叶子节点(游戏结束位置),然后进行获胜的初始移动,辞职或进行平局。

问题在于细节:大约有10 43个可能的位置,甚至还有更多的移动(大多数位置可以通过一种以上的方式到达)。您确实需要一台功能强大的计算机来利用此功能,因为可以利用此算法的计算机要么无法放入已知的Universe中,要么要等到Universe结束后的某个时间才能完成计算。


13
@Wildcard不,它不做任何假设:它只包含所有可能的国际象棋合法游戏,并且会选择所有在手边不会输的棋子。
gentil '17

11
@gented,我指的是算法的“辞职”步骤。这根本不是必需的步骤。
通配符

38
三重复规则限制了搜索空间,因此计算机不必无穷无尽,而不必只是天文数字。
Hoa Long Tam

9
作为参考,将可能的博弈数(10 ^ 120)的下限与可观察的宇宙中的原子数(约10 ^ 80)进行比较。最简单的算法必须找到所有这些游戏并存储其数据。每个原子存储一个游戏所需的原子数是我们在可观测宇宙中估计的原子数的10 ^ 40倍。
Engineer Toast

6
直到最后,当您提到“功能强大的计算机”时,这个答案都是不错的选择。那不是你的意思,这个短语既不属于问题也不属于讨论范围。
唐·哈奇

25

请参阅https://en.wikipedia.org/wiki/Endgame_tablebase

借助无限的计算机功能,人们可以为起跑位置建立一张这样的桌子并解决象棋

实际上,使用当前的超级计算机只能解决最多具有七个“人”(棋子,国王数)的位置,因此我们离解决国际象棋还很遥远。问题的复杂性随件数成倍增加。


9
附带说明一下,如果您实际上生成了这样一个表,则无论您将信息存储在什么表上,它的重量大约是可观察到的宇宙的10 ^ 43倍;考虑到在可观察的宇宙中可能有约10 ^ 123个国际象棋位置和只有约10 ^ 80个重子。
Shufflepants

6
@Shufflepants谁说我是用重笔来存储它的?
迈克尔(Michael)

3
@Christoph并假设保存了信息,并假设您拥有一台具有无限处理能力的检测器和超级计算机,那么您可以在像googolplex年这样的过程中慢慢读取表库,作为小贩辐射。
Shufflepants

3
@Shufflepants请注意,实际的获胜策略可能需要的空间比完整的数据库要少得多。例如,尼姆(Nim)的制胜战略很容易描述,不需要建立所有可能状态的庞大表格。
Federico Poloni

1
如上所述的解决方案是不可行的。这样的表的质量将形成一个黑洞,并且不可能从该表中窃取数据。
emory

19

如果您确实具有无限的处理能力,那么编写这样的算法实际上是微不足道的。由于国际象棋具有有限数量的可能状态,因此从理论上讲,您可以仅遍历所有这些状态,直到找到完美下棋的路径。这将是非常低效的,但是如果您具有无限的处理能力,那就没关系了。


这不是真的。他说您拥有无限的处理能力,但没有对无限的空间一言不发。
ubadub

@ubadub:我们不需要无限的空间。由于50步规则,游戏的时长受到限制,可以制定一个规则来对一个位置上所有可能的移动进行排序。由于可以对其进行排序,因此可以将它们存储为整数。这是遍历整棵树所需的全部内存。而且,如果您有无限的时间,则可以随心所欲地走树,因此不必存储所有可能的国际象棋游戏。
vsz

游戏的时间是有限的,但是却非常大。正如其他人指出的那样,如果您生成一个表来存储所有这些游戏,“无论您存储什么信息,它的重量大约是可观察到的宇宙的10 ^ 43倍;考虑到可能存在〜10 ^ 123国际象棋位置和可观察到的宇宙中只有约10 ^ 80个重子
ubadub

2
@ubadub:的确如此,但我并不是在谈论“用于存储所有此类游戏的表”。有许多与树相关的算法,不必将整个树的所有节点都保存在内存中。
vsz

@ vsz好点
ubadub

13

直接解决这个问题:是的,有这样一种算法。它称为极小极大。(最终游戏表库是通过使用此算法生成的(向后!),但是您只需要普通的简单minimax算法即可)。该算法可以完美地玩任何两个玩家的零和游戏。在这里找到伪代码:

https://zh.wikipedia.org/wiki/Minimax

请注意,现代计算机国际象棋程序使用了此算法的变体。


4

不仅有一种算法可以完美地下棋,还可以编写一个简短的程序(在给定的无限资源的情况下)完美地任何具有确定性的,有知识的,有限时长的两人游戏

游戏引擎甚至不需要知道它正在玩的游戏规则。它所需要的只是“游戏状态”的不透明表示,其功能是(a)给出任何游戏状态,提供合法的下一游戏状态列表,以及(b)给出游戏状态,确定是否对玩家1有利。 ,玩家2的胜利,平局,或者不是结束状态。

给定这些功能,一个简单的递归算法可以“解决”游戏。

国际象棋编程器(minimax)和累积(在python中提供了该程序的版本)在以前的答案中都提到了这一事实。

我在20多年前编写了这样的程序。我通过打零交叉游戏(如果您是美国人,则打井字游戏)进行了测试。果然它玩得很完美。

当然,对于任何严肃的游戏,这将在任何可以想象的计算机上迅速消失。由于它是递归的,因此可以有效地在堆栈上构建整个游戏树,因此在分析其他答案中提到的10 ^ 123下棋状态之前,您将获得“堆栈溢出”(非常有意思的双关语)。但有趣的是,原则上这个小程序可以完成这项工作。

对我来说,这也说明了AI的一些有趣之处:无论您认为“深蓝”或“零归零”,还是有人下象棋或“归零”表现出多少“智能”,这些游戏都具有微不足道的,可精确计算的最佳感觉解决方案。面临的挑战是如何在合理的时间内获得良好的解决方案,而不是最佳的解决方案。


您的算法仅适用于具有完善知识的两人游戏。对于诸如Stratego之类的隐藏信息游戏,它将失效,因为函数(a)的任何实现都违反了游戏规则。对于可能无限期的游戏,它也会失败:例如,从国际象棋上删除50步规则,并且不能说两个国王在棋盘上互相追逐不是一个可获胜的状态。它能说明的不是结束状态。
马克

有效点。我将编辑我的答案。
Gareth

3

为了简单起见,我将忽略平局或无限移动顺序的可能性。一旦理解了算法,将其扩展到那些情况就不会特别困难。

首先,一些定义:

  1. 对于做出此举的玩家而言,任何赢得比赛的举动都是获胜的举动。

  2. 对于做出此举的玩家而言,任何输掉比赛的举动都是失败的举动。

  3. 任何使另一方玩家至少获胜的举动也是失败的举动。(因为对手可以采取该行动并造成损失。)

  4. 任何让其他玩家只输掉棋子的举动也是获胜的棋子。(无论对手采取什么行动,您都将获胜。)

  5. 完美的策略意味着,只要有剩余的动作,就总是做出获胜的举动;而仅剩下剩余的动作时,就辞职。

现在,编写完美的策略很简单。只需分解所有可能的移动顺序并确定获胜/失败的举动。忽略僵局,最终将每一步识别为获胜或失败。

现在,该策略是微不足道的。查看您所有可能的举动。如果还有任何获胜的举动,则采取一个并获胜。如果只剩下失败的动作,请辞职,因为对手会迫使您失败。

调整策略以包括僵局的可能性并不难。

更新:如果尚不清楚如何将每一步识别为获胜或失败,请考虑:

  1. 每一个导致胜利的举动都是胜利。
  2. 导致亏损的每一步都是失败的举动。
  3. 导致对手只有获胜或失败的举动的每一步都是获胜或失败的举动。
  4. n在尽可能长的国际象棋游戏中调用步数。(尽管包括它们并不困难,我们现在暂时忽略无限制的序列。)
  5. 有没有行动n,我们需要考虑之前移动。
  6. 由于n-1先行n结束了最长的游戏,因此先行的每一步要么是获胜,要么是失败。
  7. 因此,在深处的每一个动作都n-2仅跟随获胜动作或失败动作,因此其本身就是获胜动作或失败动作。
  8. 依此类推,回到第一步。

1
您对成功和失败举动的定义不够全面。例如,第一个举动既不会赢得比赛(#1),也不会只留下失败的举动(#4)留给对手,因此它不是“胜利的举动”。它既不会输掉比赛(#2),也不会让对手留下任何获胜的举动(#3),因此这不是“失败的举动”。您的策略要求将每个举动定义为“获胜举动”或“失败举动”,而正如您所定义的那样,情况并非如此。
核王

2
@NuclearWang确实将每一步定义为获胜或失败。您认为第三个选择是什么?可视化所有可能的国际象棋游戏的树(记住,我们现在不包括平局或无限序列)。每条链条都以胜利或失败为结尾。这渗入树中,最终将每一步识别为获胜或失败。
David Schwartz

13
@NuclearWang第一个举动一个玩家的获胜举动,或者国际象棋是像打井游戏一样具有完美玩法的平局游戏。我们不知道是哪一个,因为没有人拥有执行此算法所需的计算能力,也没有人找到更直接的证明。
hobbs

8
国际象棋中没有随机性,也没有隐藏的信息,因此没有留出“也许”的空间。每个职位都会获胜,丢失或平局(即使我们未能设法将其识别出来)。而且,为了简化起见,此解释省略了“绘制”选项,但它主要相当于1)如果根据规则绘制,则绘制一个头寸,以及2)如果没有获胜举动,但具有至少使对手无获胜的一招。
hobbs

2
@DavidSchwartz:除非有人处于亏损位置,否则所有不完美的举动都是不好的。在失败的位置上,通常不会有一个“完美”的举动(在强迫移动情况下除外),因为在某些可能的(可能是高度人为的)情况下,任何合法举动都可能是唯一的获胜或平局举动。但是,辞职似乎是最明确的最糟糕的“举动”。假设该游戏被证明是d4赢得White的胜利。你想玩哪个回答了国际象棋程序1. d4...resigns
超级猫

2

假设你有三个功能:win_stateget_player,和next_states。输入的win_state是游戏状态,如果白色处于将死状态,则输出为-1;如果是平局,则输出为0;如果黑色处于将死状态,则输出为1,None否则。输入为get_player游戏状态,如果是黑色则为-1,如果是白色则为1。输入的信息next_states是合法举动可能导致的下一个游戏状态列表。然后,以下功能(在给定游戏状态和玩家时)应该告诉您要使该玩家获胜的游戏状态。

def best_state(game_state,player)
  def best_result(game_state):
     if win_state(game_state):
        return(win_state)
     else:
         player = get_player(game_state)
         return max([best_result(move)*player for move in next_states(game_state)])*player
  cur_best_move = next_states(games_state)[0]
  cur_best_outcome = -1
  for state in next_states(game_state):
     if best_result(state)*player > cur_best_outcome:
           cur_best_outcome = best_result(state)*player
           cur_best_move = state
return(best_move)

0

使用查询表

是。这简单。您甚至不需要无限的处理能力。您所需要的就是一张查找表,其中包含每个棋盘位置的最佳移动位置。这是伪代码:

def play-move(my-color, board-position):
    return table-of-best-moves[my-color, board-position]

抓住

唯一的问题是,该查找表必须非常大(可能比银河系大),并且构造它的时间也很长,可能要比当前宇宙时代长,除非存在国际象棋中一些未发现的规律性使其比我们现在所看到的要简单得多。但是,如果您有此查询表,则每次只需选择一条CPU指令即可实现每次选择一个完美动作的子例程。

另外,考虑到我们目前对国际象棋的了解,因此无法确保完美的打法保证您不会输。例如,如果完美打法保证白方获胜,那么即使黑色打法完美,黑方也会输。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.