【问题标题】:How to get a list of the Value of a number as the sum of 4 numbers in Prolog如何在Prolog中获取一个数字的值列表作为4个数字的总和
【发布时间】:2014-05-31 15:35:56
【问题描述】:

我无法使这个谓词工作。这个想法是使用diabolic([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]) 来获取该列表中所有可能的幻方。

起初我考虑使用permutation/2,但对于 16 个数字的列表来说它太慢了。

然后我在这里找到了一个使用外部库 (clpfd) 并具有出色性能的示例,但我试图在没有任何外部库的情况下解决它......所以我尝试了这样的事情:

sum([X,Y,Z,W]) :-
  A = [1..16],
  member(X,A),
  member(Y,A),
  member(Z,A),
  member(W,A),
  X \== Y,
  X \== Z,
  X \== W,
  Y \== Z,
  Y \== W,
  Z \== W,
  34 is (X+Y+Z+W).

我正在尝试做的是获取所有可能的不同数字的列表,总和为 34,因此我可以检查哪个组合构成一个幻方(希望使其比使用正常排列更快。

不过,我收到了关于 member(X,[1..16]), 中预期的某些运算符的错误,所以也许我做错了什么。我对 Prolog 很陌生,所以我希望能得到你们的帮助。

提前致谢。

【问题讨论】:

标签: prolog magic-square


【解决方案1】:

查看以下链接,我使用了其中一个程序,它解决了与排列相同的问题:

prolog I have to make a program that calculates the magic matrix permutate

【讨论】:

    【解决方案2】:

    您走在正确的轨道上:尽快实施约束,以修剪搜索空间。

    问题是如何“拆分”排列过程,以便能够尽快修剪结果。

    简单的方法:

    diabolic([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]) :-
        N0=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],
    
        R1=[A,B,C,D],select_list(N0,R1,N1),sum_list(R1,34),
        R2=[E,F,G,H],select_list(N1,R2,N2),sum_list(R2,34),
        R3=[I,J,K,L],select_list(N2,R3,N3),sum_list(R3,34),
        R4=[M,N,O,P],select_list(N3,R4,[]),sum_list(R4,34),
    
        sum_list([A,E,I,M],34),
        sum_list([B,F,J,N],34),
        sum_list([C,G,K,O],34),
        sum_list([D,H,L,P],34),
    
        sum_list([A,F,K,P],34),
        sum_list([M,J,G,D],34).
    
    select_list(X,[],X).
    select_list(X,[H|T],Z) :- select(H,X,Y), select_list(Y,T,Z).
    

    这仍然比 CLP(FD) 慢得多,但可以作为一个起点...

    编辑简单的代码改进。

    原作:

    ?- forall(time(diabolic(L)),writeln(L)).
    % 74,769,227 inferences, 23.739 CPU in 23.754 seconds (100% CPU, 3149688 Lips)
    [1,2,15,16,12,14,3,5,13,7,10,4,8,11,6,9]
    % 7,556,909 inferences, 2.396 CPU in 2.448 seconds (98% CPU, 3154252 Lips)
    [1,2,15,16,13,14,3,4,12,7,10,5,8,11,6,9]
    % 90,103,270 inferences, 28.475 CPU in 28.503 seconds (100% CPU, 3164265 Lips)
    [1,2,16,15,13,14,4,3,12,7,9,6,8,11,5,10]
    Action (h for help) ? aabort
    

    内联 select_list/3

    select_(N0,[A,B,C,D],N1) :-
        select(A,N0,T0),
        select(B,T0,T1),
        select(C,T1,T2),
        select(D,T2,N1).
    
    diabol_1([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]) :-
        N0=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],
        R1=[A,B,C,D],select_(N0,R1,N1),sum_list(R1,34),
        R2=[E,F,G,H],select_(N1,R2,N2),sum_list(R2,34),
        R3=[I,J,K,L],select_(N2,R3,N3),sum_list(R3,34),
        R4=[M,N,O,P],select_(N3,R4,[]),sum_list(R4,34),
    
        sum_list([A,E,I,M],34),
        sum_list([B,F,J,N],34),
        sum_list([C,G,K,O],34),
        sum_list([D,H,L,P],34),
    
        sum_list([A,F,K,P],34),
        sum_list([M,J,G,D],34).
    

    我们得到了一个小改进:

    ?- forall(time(diabol_1(L)),writeln(L)).
    % 65,282,719 inferences, 21.137 CPU in 21.195 seconds (100% CPU, 3088524 Lips)
    [1,2,15,16,12,14,3,5,13,7,10,4,8,11,6,9]
    % 6,607,508 inferences, 2.074 CPU in 2.075 seconds (100% CPU, 3186362 Lips)
    [1,2,15,16,13,14,3,4,12,7,10,5,8,11,6,9]
    % 78,691,563 inferences, 24.914 CPU in 24.928 seconds (100% CPU, 3158505 Lips)
    [1,2,16,15,13,14,4,3,12,7,9,6,8,11,5,10]
    Action (h for help) ? aabort
    

    内联 sum_list/2 我们看到了进一步的小收获:

    sum_([A,B,C,D]) :- A+B+C+D =:= 34.
    
    diabol_2([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]) :-
        N0=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],
        R1=[A,B,C,D],select_(N0,R1,N1),sum_(R1),
        R2=[E,F,G,H],select_(N1,R2,N2),sum_(R2),
        R3=[I,J,K,L],select_(N2,R3,N3),sum_(R3),
        R4=[M,N,O,P],select_(N3,R4,[]),sum_(R4),
    
        sum_([A,E,I,M]),
        sum_([B,F,J,N]),
        sum_([C,G,K,O]),
        sum_([D,H,L,P]),
    
        sum_([A,F,K,P]),
        sum_([M,J,G,D]).
    
    ?- forall(time(diabol_2(L)),writeln(L)).
    % 20,419,167 inferences, 10.425 CPU in 10.431 seconds (100% CPU, 1958699 Lips)
    [1,2,15,16,12,14,3,5,13,7,10,4,8,11,6,9]
    % 2,058,108 inferences, 1.046 CPU in 1.047 seconds (100% CPU, 1966993 Lips)
    [1,2,15,16,13,14,3,4,12,7,10,5,8,11,6,9]
    % 24,592,123 inferences, 12.462 CPU in 12.481 seconds (100% CPU, 1973394 Lips)
    [1,2,16,15,13,14,4,3,12,7,9,6,8,11,5,10]
    Action (h for help) ? aabort
    

    【讨论】:

    • 确实比较慢,但现在我开始在不到一分钟的时间内得到结果。这是一个很大的帮助,我会尝试完善这个想法,看看我是否可以获得更好的结果。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 2022-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-02
    • 2022-08-08
    相关资源
    最近更新 更多