使用Prolog实现八(非攻击)骑士



我目前正在研究一种算法,旨在找到问题的所有解决方案,"有多少种方法可以将8个骑士放在8x8的棋盘上,使它们都不能互相攻击?"

现在我已经能够应用8皇后8x8棋盘解决方案,解决我在网上找到的8皇后算法中关于8个主教和8个白头鸦的类似问题。(因为象和车沿着对角线或水平/垂直方向移动,这与皇后的算法非常相似)

这是我到目前为止写的。

solution([]).
solution([X/Y|Others]) :-
   solution(Others),
   member(Y, [1, 2, 3, 4, 5, 6, 7, 8]),
   noattack(X/Y, Others).

noattack(_,[]).
noattack(X/Y, [X1/Y1|Others]):-
      Y1 - Y == 2, X1 - X == 1
   ;  Y - Y1 == 2, X1 - X == 1
   ;  Y1 - Y == 2, X - X1 == 1
   ;  Y - Y1 == 2, X - X1 == 1
   ;  Y1 - Y == 1, X1 - X == 2
   ;  Y - Y1 == 1, X1 - X == 2
   ;  Y1 - Y == 1, X - X1 == 2
   ;  Y - Y1 == 1, X - X1 == 2
   ;  noattack(X/Y, Others).     
template([1/Y1, 2/Y2, 3/Y3, 4/Y4, 5/Y5, 6/Y6, 7/Y7, 8/Y8]).
main :-
    open('knights.out',write,ID),
    (   ( template(X), solution(X), write(ID,X), nl(ID), fail )
       ; close(ID)
    ).

基本上,我或多或少地模仿了标准的8-Queens Prolog算法,但不是比较Y和Y1的潜在"水平"潜在攻击和Y1-Y == X1 - X和Y1-Y == X - X1的对角线潜在攻击,就像我对女王所做的那样,这次我比较了下一个可能点的每个确切位置与当前骑士可以攻击的任何地方,并将其统一为统一的东西。(抱歉,作为一个专注于Python的CS学生,我真的不擅长解释这一点。如果你在这之前还没有起床,请查看http://www.javaist.com/blog/2008/11/06/eight-queens-problem-in-prolog/)他很好地解释了什么是8皇后算法。

标准的运行方式是。

?- template(A), solution(A).

,然后在第一次统一时,按"a"以便在gprolog或swiprolog交互控制台中打印出所有解决方案。对于8皇后,只有32个解决方案,因此,可以在回溯序列中逐行计数32,以验证算法。但对于8骑士问题,将有379978716个有效的解决方案(根据http://oeis.org/search?q=nonattacking%20knights&sort=&language=&go=Search)。这就是最后"main"函数发挥作用的地方。这基本上将每个统一打印到一个名为"骑士"的文件中。所以我可以在代码编辑器中打开它,看看是否有379978716行。

运行,一些计算,我计算出输出文件应该在14 gigs左右,但我的算法目前产生的文件大于70G(可能是无限循环,但我的Linux Partitian只能存储70G,所以我不知道)。但不管怎样,这个算法会重复计算几次,我不知道如何解决这个问题。

任何帮助都会很感激。(为了简洁,我没有上传八主教和八白嘴鸦的代码,但如果你感兴趣,我把它们保存在这里:https://github.com/gilgameshskytrooper/eightqueens)

您在评论中指出的解决方案是不正确的。我想提出一些改进建议:而不是:

noattack(X/Y, [X1/Y1|Others]):-
    Y1 - Y == 2, X1 - X == 1;
    Y - Y1 == 2, X1 - X == 1;
    Y1 - Y == 2, X - X1 == 1;
    Y - Y1 == 2, X - X1 == 1;
    Y1 - Y == 1, X1 - X == 2;
    Y - Y1 == 1, X1 - X == 2;
    Y1 - Y == 1, X - X1 == 2;
    Y - Y1 == 1, X - X1 == 2;
    noattack(X/Y, Others).

你可以简单地使用abs并写:

noattack(X/Y, [X1/Y1|Others]):-
  Y == Y1,
  abs(Y1-Y) == abs(X1-X),
  noattack(X/Y,Others).

在上面的谓词中,我们不需要写:X == X1,因为由于模板的关系,我们假设X是不同的。

这没有回答问题,但这是一个更好的方式来写它,它不适合在注释…

最新更新