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

旧城冷巷雨未停 提交于 2019-12-13 16:19:18

问题


I have to make a program that calculates the magic matrix, I have made ​​my code and it works but my permute is very slow. I need one that is faster someone can help me Please

This is the code:

diabolico([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]) :- 
    permutar([1,14,3,16,5,12,13,15,9,10,11,6,7,2,8,4],[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,
    M+B+G+L=:=34, I+N+C+H=:=34, E+J+O+D=:=34, A+F+K+P=:=34,
    P+C+F+I=:=34, L+O+B+E=:=34, H+K+N+A=:=34, D+G+J+M=:=34.   

permutar([],[]). 
permutar([X|Y], Z):-
    permutar(Y,L),
    insertar(X,L,Z). 

insertar(E,L,[E|L]). 
insertar(E, [X|Y], [X|Z]):-
    insertar(E, Y, Z).

回答1:


Constraint logic programming works good for this kind of problems by dramatically pruning search space.

Program in ECLiPSe (can be easily translated to work with other modern Prolog systems):

:- lib(ic).

diabolico([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]) :- 
    Vars = [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P],
    Vars :: 1..16,
    alldifferent(Vars),
    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,
    M+B+G+L #= 34, I+N+C+H #= 34, E+J+O+D #= 34, A+F+K+P #= 34,
    P+C+F+I #= 34, L+O+B+E #= 34, H+K+N+A #= 34, D+G+J+M #= 34,
    labeling(Vars).

Works instantly:

[eclipse]: diabolico([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]).
A = 1
B = 8
C = 10
D = 15
E = 12
F = 13
G = 3
H = 6
I = 7
J = 2
K = 16
L = 9
M = 14
N = 11
O = 5
P = 4
Yes (0.02s cpu, solution 1, maybe more)



回答2:


You could try to use permutation/2, maybe it's faster than your (I'm not sure, should benchmark it). Anyway, permutations often call for a different approach, for instance CLP(FD). I copied your code, and modified it:

:- use_module(library(clpfd)).

diabolico([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P]) :-
 Vs = [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P],
 Vs ins 1..16,
 all_different(Vs),
 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,
 M+B+G+L#=34,
 I+N+C+H#=34,
 E+J+O+D#=34,
 A+F+K+P#=34,
 P+C+F+I#=34,
 L+O+B+E#=34,
 H+K+N+A#=34,
 D+G+J+M#=34,
 label(Vs).

writerows([]).
writerows([A,B,C,D|Rs]) :-
 format('~|~t~d~3+~|~t~d~3+~|~t~d~3+~|~t~d~3+~n', [A,B,C,D]),
 writerows(Rs).

here is a sample out:

?- diabolico(X), writerows(X).
  1  8 10 15
 12 13  3  6
  7  2 16  9
 14 11  5  4
X = [1, 8, 10, 15, 12, 13, 3, 6, 7|...] ;
  1  8 10 15
 14 11  5  4
  7  2 16  9
 12 13  3  6
X = [1, 8, 10, 15, 14, 11, 5, 4, 7|...] ;
  1  8 11 14
 12 13  2  7
  6  3 16  9
 15 10  5  4
X = [1, 8, 11, 14, 12, 13, 2, 7, 6|...] 
...

My compliments for your permutar/2 implementation: it's far better than permutation/2:

?- X=[1,2,3,4,5,6,7,8], time(aggregate(count,X^Y^permutation(X,Y),C)).
% 328,837 inferences, 0.171 CPU in 0.172 seconds (99% CPU, 1927406 Lips)
X = [1, 2, 3, 4, 5, 6, 7, 8],
C = 40320.

?- X=[1,2,3,4,5,6,7,8], time(aggregate(count,X^Y^permutar(X,Y),C)).
% 86,597 inferences, 0.079 CPU in 0.081 seconds (99% CPU, 1091190 Lips)
X = [1, 2, 3, 4, 5, 6, 7, 8],
C = 40320.

Alas, then my initial suggestion is totally useless...




回答3:


takeout(H,[H|R],R).
takeout(H,[F|S],[F|R]) :- takeout(H,S,R).
perm([],[]).
perm([H|T],S) :- perm(T,R), takeout(H,S,R).  
line([X,Y,Z], S) :- S is X+Y+Z.
magic([A,B,C, D,E,F, G,H,I]) :- line([A,B,C],S), line([D,E,F],S), line([G,H,I],S), line([A,D,G],S), line([B,E,H],S), line([C,F,I],S).
solve(S) :- perm([1,2,3,4,5,6,7,8,9],S), magic(S).

Can solve a 9*9 square with the following example call:

?- solve([1,B,C,D,E,2,G,3,J]).

Will show:

B = 8,
C = 6,
D = 9,
E = 4,
G = 5,
J = 7 ;
B = 5,
C = 9,
D = 6,
E = 7,
G = 8,
J = 4 ;
false.


来源:https://stackoverflow.com/questions/23939565/prolog-i-have-to-make-a-program-that-calculates-the-magic-matrix-permutate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!