0

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?

false
  • 10,264
  • 13
  • 101
  • 209
Enoon
  • 421
  • 4
  • 17
  • 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`? –  Mar 25 '13 at 10:12
  • Typo in posting here the question, i'll fix it! – Enoon Mar 25 '13 at 10:37
  • Read this nice intro: http://web.student.tuwien.ac.at/~e0225855/acomip/acomip.html – false Mar 25 '13 at 15:27
  • [Copy for above reference](http://www.complang.tuwien.ac.at/ulrich/prolog_misc/acomip.html) – false Mar 25 '13 at 15:39

1 Answers1

1

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)

CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • Thanks! The only problem is that it hangs if you give him something supposed to fail. Ex: solve2((c(A,B,_),a(A),b(2,B))). Do you have an idea why? :) – Enoon Mar 25 '13 at 11:35
  • See last edit, I've added a cut, seems to work (i.e. fail) now. – CapelliC Mar 25 '13 at 11:45
  • Thanks, this is great. I had a similar problem to yours on predicates that were supposed to fail - i have to learn to use the cuts as well as you. :) – Enoon Mar 25 '13 at 12:28
  • There is still one big problem: if you give it as input solve2((b(A,B),a(A),c(A,B,C))) it will give out the wrong order because b(A,B) will be executed _after_ the (a(A),c(A,B,_)) block. – Enoon Mar 25 '13 at 14:23