1
votes

I'm attempting to write a Prolog meta-interpreter to choose the order of goal execution, for example executing first all goals with the minimum number of parameters.

I started from the vanilla meta-interpreter:

solve2(true).
solve2(A) :- builtin(A), !, A.
solve2((A,B)) :- solve2(A), solve2(B).
solve2(A) :- clause(A,B), solve2(B).

Then i went to something like

solve2(true).
solve2(A) :- builtin(A), !, A.
solve2((A,B)) :- count(A,Args), count(B,Args2), Args<Args2, solve2(A), solve2(B).
solve2((A,B)) :- count(A,Args), count(B,Args2), Args>Args2, solve2(B), solve2(A).
solve2(A) :- clause(A,B), solve2(B).

But if the 4th line is executed then the whole block B is executed before A which is wrong.

Ex. A=a(x,y), B=(b(x,y,z), c(x)) I'd like to execute c, then a, then b. - while in this method i'd get c, b and then a. I'm thinking about transforming the goals in a list but i'm not too sure.

Any ideas?

1
Without going deeper in the logic of your program, you realize that in line 4 of the second listing there is a Args>Args (which will never be true), while I think you mean to say Args>Args2? - user1812457
Typo in posting here the question, i'll fix it! - Enoon

1 Answers

2
votes

Here is an (untested) vanilla meta interpreter, with conjunction order changed. I would be glad if you could try with your data.

solve2(true).
solve2(A) :- builtin(A), !, A.
solve2((A,B)) :- ordering(A,B, C,D), ! /* needed */, solve2(C), solve2(D).
solve2(A) :- clause(A,B), solve2(B).

ordering(A,B, C,D) :-
    minargs(A, NA),
    minargs(B, NB),
    ( NA =< NB -> C/D=A/B ; C/D=B/A ).

minargs((A,B), N) :-
    minargs(A, NA),
    minargs(B, NB),
    !, ( NA =< NB -> N=NA ; N=NB ).
minargs(T, N) :-
    functor(T, _, N).

edit I tested with this setting:

builtin(writeln(_)).

a(1):-writeln(1).
b(1,2):-writeln(2).
c(1,2,3):-writeln(3).

test :-
    solve2((c(A,B,_),a(A),b(A,B))).

and got the expected output:

?- test.
1
2
3
true .

edit I had to resort to a list representation, but then it make sense to preprocess the clauses and get the right order before, then stick to plain vanilla interpreter:

test :-
    sortjoin((b(A,B),a(A),c(A,B,_)), X),
    solve2(X).

sortjoin(J, R) :-
    findall(C-P, (pred(J, P), functor(P,_,C)), L),
    sort(L, T),
    pairs_values(T, V),
    join(V, R).

join([C], C).
join([H|T], (H,R)) :- join(T, R).

pred((A, _), C) :-
    pred(A, C).
pred((_, B), C) :-
    !, pred(B, C).
pred(C, C).

where solve2((A,B)) :- ... it's the original solve2(A),solve2(B)