Prolog循环,直到返回true

Prolog循环,直到返回true,prolog,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,

我正在尝试生成一个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没有传统意义上的循环,但我不太明白在找到有效案例之前如何运行(我也知道这里使用的暴力方法可能需要相当长的时间)


任何关于解决这一问题的见解都将不胜感激

您的程序需要另一种方法

只要看看目标:

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个!解决。换言之:2092789888000。所以,如果你有一台快速的电脑在你的支配下

为了改善这种情况,我们必须减少解决方案或答案的数量。但是,如何?Prolog有一些非常好的功能:逻辑变量。也就是说,我们可以使用约束将许多解决方案包含在单个答案中。在这种情况下,
库(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.
一个答案现在包含了所有20万亿个解决方案!通过进一步的限制,我们现在可以写:

:- 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
让打印由顶级完成!
正如您所看到的,Prolog现在可以不可思议地快速找到所有这些魔法方块

“我不太明白在找到一个有效的案例之前如何运行”只要调用谓词,这正是Prolog将要做的。但你的方法似乎效率很低,这就是为什么它似乎不起作用的原因。
?- 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]] ...