prologmetaprogrammingprolog-metainterpreter

Change goal execution order in Prolog Interpreter


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?


Solution

  • 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)