问题描述
许多 Prolog 系统同时实现了制表。 SWI-Prolog 采用了 很多 XSB 表。 XSB 表建议转换游戏搜索:
win(X) :- move(X,Y),\+ win(Y).
进入这个表:
:- table win/1.
win(X) :- move(X,tnot(win(Y))
在实际游戏搜索中是否值得考虑为游戏搜索做表? 对井字游戏有何影响?
解决方法
我的出发点是 Prolog Tic-Tac-Toe tictac.p,链接在帖子末尾。但我没有使用 tnot/1,只使用 table/1 指令。首先,我们必须小心添加正确的表格。
因此,下面首先添加 table/1 指令是无稽之谈,因为作为失败元参数的否定中的 best/3 递归调用具有隐式存在量词。第三个参数将使最佳/ 3 非确定性 并炸毁桌子:
:- table best/3.
best(X,P,Y) :-
move(X,Y),(win(Y,P) -> true;
other(P,Q),\+ tie(Y,\+ best(Y,Q,_)).
更好的方法是只将 best/3 的第一个解决方案引入 一个新的谓词 best/2。这不会改变否定的结果 作为失败。然后列出这个新谓词 best/2:
:- table best/2.
best(X,P) :-
best(X,_),!.
best(X,Q)).
有趣的发现,SWI-Prolog 否定作为失败要快得多 比我的,但它被一些开销所困扰,因为什么时候 切换到牌桌无法加快游戏搜索速度。曾是 比较 Prolog 文本 tictac.p 和 tictac2.pl:
/* SWI-Prolog 8.3.19 */
?- time((between(1,50,tictac,fail; true)).
% 5,087,251 inferences,1.034 CPU in 1.044 seconds (99% CPU,4920224 Lips)
true.
?- time((between(1,abolish_all_tables,fail; true)).
% 4,472,1.343 CPU in 1.426 seconds (94% CPU,3329897 Lips)
true.
另一方面,我得到了一个 ca。两倍加速:
/* Jekejeke Prolog 1.4.7 */
?- time((between(1,fail; true)).
% Up 3,218 ms,GC 10 ms,Threads 3,201 ms (Current 02/14/21 01:04:15)
Yes
?- time((between(1,retractall_table(_),fail; true)).
% Up 1,703 ms,GC 11 ms,Threads 1,688 ms (Current 02/14/21 01:06:50)
Yes
开源:
井字游戏,无需打桌
https://github.com/jburse/jekejeke-samples/blob/master/jekrun/benchmark/tests/tictac.p
井字游戏与桌子
https://gist.github.com/jburse/713b6ad2b7e28de89fe51b98be3d0943#file-tictac2-pl