Prolog 关于使用置换的8皇后解的一些解释

Prolog 关于使用置换的8皇后解的一些解释,prolog,n-queens,Prolog,N Queens,我正在为一个关于SWI Prolog实现的大学考试学习Prolog 我对这个版本的8皇后问题如何使用排列来解决这个问题有一些疑问: solution(Queens) :- permutation([1,2,3,4,5,6,7,8], Queens), safe(Queens). permutation([],[]). permutation([Head|Tail],PermList) :- permutation(Tail,PermTail), del(Head,PermList,P

我正在为一个关于SWI Prolog实现的大学考试学习Prolog

我对这个版本的8皇后问题如何使用排列来解决这个问题有一些疑问:

solution(Queens) :-
 permutation([1,2,3,4,5,6,7,8], Queens),
 safe(Queens).

permutation([],[]).

permutation([Head|Tail],PermList) :-
 permutation(Tail,PermTail),
 del(Head,PermList,PermTail).

del(Item,[Item|List],List).

del(Item,[First|List],[First|List1]) :-
 del(Item,List,List1).

safe([]).

safe([Queen|Others]) :-
 safe(Others),
 noattack(Queen,Others,1).

noattack(_,[],_).

noattack(Y,[Y1|Ylist],Xdist) :-
 Y1-Y=\=Xdist,
 Y-Y1=\=Xdist,
 Dist1 is Xdist + 1,
 noattack(Y,Ylist,Dist1).
在以前的解决方案中,我使用了这个解决方案模板:[1\Y1,2\Y2,3\Y3,4\Y4,5\Y5,6\Y6,7\Y7,8\Y8],它简单地说每个皇后必须在不同的行上,X计算可以被约束

这个版本的程序有很大的不同,因为我们可以观察到,为了防止垂直攻击,所有的皇后必须在不同的行上,所以每行有一个皇后

因此,在不丢失信息的情况下,我可以说,解决方案将是列表的排列:[1,2,3,4,5,6,7,8],其中每个元素表示女王的Y坐标

因此,在本例中,我仅通过Y坐标(其行索引)表示皇后位置

因此,我有解的关系,而不是说如果queen是[1,2,3,4,5,6,7,8]原始列表的预置换,并且如果这个置换是安全的(这个置换列表中的每个皇后都不会攻击其他皇后),那么列表queen就是一个解

好的,这很清楚…现在定义了安全关系

有一个基本情况表明,如果列表为空,那么这是安全的,因为没有攻击

通常情况下,列表不是空的。如果列表不是空的,我可以将其划分为[Queen | Others],其中Queen是列表中的第一个Queen,而Others是剩余的子列表……因此原始列表[Queen | Others]是安全的,如果子列表本身就是一个解决方案(如果它是安全的,如果其他人没有攻击)并且如果第一个项目皇后不攻击其他子列表中的其他皇后

好吧…直到现在我觉得我很清楚

现在我对noattack关系的定义有一些问题

问题是,我只通过它的Y坐标和X坐标来表示皇后位置 不明确地存在

我了解到,为了规避RAP演示文稿的这一限制,有以下概括(我希望理解得很好……我不太确定……)**我还知道,董事会的每一列上都必须有一个皇后,因此与列表中第一个皇后(皇后)和子列表中其他皇后的X距离必须为1**

其中,与第一个项目皇后和子列表Others的距离是与第一个项目皇后和离它最近的皇后的X距离,这符合我的推理吗

因此,如果皇后位于不同的列上,则noattack关系为真(对于构造而言始终为真),我可以表示必须位于不同的行上,表示与皇后和其他子列表中最近皇后的X距离为1

但是,如果我的推理是正确的,那么我在试图理解rap如何在代码的这一部分中表达这一点时会遇到很多困难:

noattack(Y,[Y1|Ylist],Xdist) :-
 Y1-Y=\=Xdist,
 Y-Y1=\=Xdist,
 Dist1 is Xdist + 1,
 noattack(Y,Ylist,Dist1).

我认为你的问题只在于这两行:

Y-Y1=/=Xdist,
Y1-Y=/=Xdist,
它检查具有Y的皇后是否以对角线方式以Xdist距离攻击该行中的皇后。(
|Y-Y1 |=Xdist-->对角线攻击

攻击其他皇后的另一种方法是将它们放在同一行中,这不会简单地发生,因为解决方案是
[1,2,3,4,5,6,7,8]
的排列。所以像
[1,1,3,4,5,6,7,8]
这样的事情永远不会发生,这足以检查对角线

我希望它解决了这个问题

p、 请注意,
Y1
是规则
Safe/1
Others
头部的Y坐标。因此它是一个皇后,其
Xdist
首先为1,然后返回到其他行

澄清 我们讨论的是
noattack/3
。您给它三个参数:

第一个
Y
当前女王的坐标

second:最右边的列表
[Y1 | Ylist]
从列表中
Y
之后的某个地方开始,并继续到主列表的末尾。(是,这是解决方案的子列表),以及

third
Xdist
是当前皇后(有Y)和皇后(有Y1,是第二个参数的头)之间的索引距离

第三个参数是必要的,因为没有它,我们无法检查当前皇后和具有Y1的皇后之间的对角交互。这是真正的基础数学,坐标系中只有两个点,只有自然数。假设这两个点以对角方式相互攻击,当且仅当abs(x1-x2)=abs(y1-y2)

如果你能很好地理解我的解释,请检查它是否被接受

P1=(3,4)和P2=(1,2)
-->
这些点具有对角攻击,因为abs(3-1)=abs(4-2)=2

示例2

P1=(3,4)和P2=(7,0)
-->
这些点具有对角攻击,因为abs(3-7)=abs(4-0)=4

这就是为什么我们同时检查
Y1-Y=\=Xdist
Y-Y1=\=Xdist
。因为每当有对角线攻击时,其中至少有一个是
true
。当其中没有一个是true时,这意味着
Y
的女王和
Y1
的女王之间没有对角线攻击。因此我们可以继续d检查下一个皇后,即
Ylist
的头

我希望这就足够了。这是一个非常简单的问题,只要仔细阅读它,如果你不能再次理解,试着自己在一张纸上追踪算法。这是一种总是有效的方法。

我有