Prolog循环返回true,返回

时间:2016-11-28 08:52:14

标签: prolog

我试图生成一个4x4魔方拼图,一旦找到有效的解决方案,就会打印出列表。我有规则打印给定的解决方案并生成随机板并解决它,但我不知道如何调用生成事实,直到它返回true,然后打印它。这是我的代码:

check([[A,B,C,D],[E,F,G,H],[I,J,K,L],[M,N,O,P]]) :-
   A+B+C+D=:=34,
   E+F+G+H=:=34,
   I+J+K+L=:=34,
   M+N+O+P=:=34,
   A+E+I+M=:=34,
   B+F+J+N=:=34,
   C+G+K+O=:=34,
   D+H+L+P=:=34,
   A+F+K+P=:=34,
   D+G+J+M=:=34.

solve([[A,B,C,D],[E,F,G,H],[I,J,K,L],[M,N,O,P]]) :-
   permutation(
          [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],
          [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]),
   check([[A,B,C,D],[E,F,G,H],[I,J,K,L],[M,N,O,P]]).

generate :-
   random_permutation(
          [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],
          [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]),
   solve([[A,B,C,D],[E,F,G,H],[I,J,K,L],[M,N,O,P]]),
   printlist([[A,B,C,D],[E,F,G,H],[I,J,K,L],[M,N,O,P]]).

printlist([X|List]) :-
    write(X),nl,
    printlist(List).

我知道Prolog没有传统意义上的循环,但是我不太清楚如何找到有效的案例(我也知道这里使用的暴力方法可以需要一段时间)。

任何有关解决此问题的见解将不胜感激!

1 个答案:

答案 0 :(得分:2)

你的程序正在呼唤另一种方法!

看看目标:

permutation(
          [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],
          [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]),

这个目标将产生16个!解决方案。换句话说:20 922 789 888 000.所以,如果你有一台快速的电脑,......

为了改善这种情况,我们必须减少解决方案或答案的数量。但是,怎么样? Prolog有一些非常好的东西:逻辑变量。也就是说,我们可以使用约束单一答案中包含许多解决方案。在这种情况下,library(clpfd)会有所帮助:

?- Xs = [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P], Xs ins 1..16, all_different(Xs).
Xs = [A, B, C, D, E, F, G, H, I|...],
A in 1..16,
all_different([A, B, C, D, E, F, G, H|...]),
B in 1..16,
C in 1..16,
D in 1..16,
E in 1..16,
F in 1..16,
G in 1..16,
H in 1..16,
I in 1..16,
J in 1..16,
K in 1..16,
L in 1..16,
M in 1..16,
N in 1..16,
O in 1..16,
P in 1..16.

一个答案现在包含所有二十亿个解决方案!有了进一步的限制,我们现在可以写:

:- use_module(library(clpfd)).

magquad_([[A,B,C,D],[E,F,G,H],[I,J,K,L],[M,N,O,P]], Zs) :-
   Xs = [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P],
   Xs ins 1..16,
   all_different(Xs),
   Zs = [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P],
   A+B+C+D#=34,
   E+F+G+H#=34,
   I+J+K+L#=34,
   M+N+O+P#=34,
   A+E+I+M#=34,
   B+F+J+N#=34,
   C+G+K+O#=34,
   D+H+L+P#=34,
   A+F+K+P#=34,
   D+G+J+M#=34.

magquad(Xss) :-
   magquad_(Xss, Zs),  % use of core-relation or model
   labeling([], Zs).   % separate labeling

让印刷完成!

?- time(magquad(Xss)).
% 106,412 inferences, 0.052 CPU in 0.053 seconds (99% CPU, 2049006 Lips)
Xss = [[1, 2, 15, 16], [12, 14, 3, 5], [13, 7, 10, 4], [8, 11, 6, 9]] ;
% 36,910 inferences, 0.027 CPU in 0.027 seconds (99% CPU, 1384976 Lips)
Xss = [[1, 2, 15, 16], [13, 14, 3, 4], [12, 7, 10, 5], [8, 11, 6, 9]] ;
% 209,488 inferences, 0.089 CPU in 0.089 seconds (100% CPU, 2348606 Lips)
Xss = [[1, 2, 16, 15], [13, 14, 4, 3], [12, 7, 9, 6], [8, 11, 5, 10]] ...

正如你所看到的,Prolog现在可以快速地找到所有那些魔方!