The first implementation of the query pack execution algorithm is the meta-interpreter meta_execute_qp(Q). The meta-interpreter uses the following labelling in its representation of a query pack:
Consider the query pack a, (b, (c or d or e) or f or g, (h or i or j)). Note that the atoms in the example could in general be arbitrary conjunctions of non-ground terms. Its labelling is shown in Figure 3.
A labelled query pack
is then represented as a Prolog term
as follows (with
the father of
):
The example of Figure 3 has the following representation (as a Prolog term):
(a, or([(b,or([(c,leaf(2,1,1)),(d,leaf(2,2,2)),(e,leaf(2,3,3))],1,2,1,3)),
(f,leaf(1,2,4)),
(g,or([(h,leaf(3,1,5)),(i,leaf(3,2,6)),(j,leaf(3,3,7))],1,3,3,3))],
0,1,1,3))
During the execution of the meta-interpreter, solved/2 facts are
asserted. Each fact solved(
,
) denotes that the
child with number
from query pack with number
has
succeeded. Such facts are asserted when reaching a leaf and also when
all children of a query pack have succeeded. The meta-interpreter
only executes children for which no solved/2 fact has been
asserted.
Note that the time-complexity of this meta-interpreter is not yet as desired. Execution of a query pack will always be dependent on the number of original children, instead of the number of remaining (as yet unsuccessful) children.
run_QueryPack(Q) :-
preprocess(Q, Qlabeled, 0, 1, 1, 1, _, _),
% The code for preprocessing is given in Appendix A
retractall(solved(_, _)),
meta_execute_qp(Qlabeled),
solved(0, _), !.
meta_execute_qp((A,B)) :- !,
call(A),
meta_execute_qp(B).
meta_execute_qp(or(Cs, QpNbF, QpNb, ChildNb, TotCs)) :-
!, % 'or' corresponds to a non-leaf query pack
handlechildren(Cs, QpNb, 1),
all_solved(QpNb, 0, TotCs),
assert(solved(QpNbF,ChildNb)).
meta_execute_qp(leaf(QpNbF, ChildNb , QueryNb)) :-
!, % 'leaf' corresponds to the end of a query
write(succeed(QueryNb)), nl,
assert(solved(QpNbF,ChildNb)).
handlechildren([], _, _).
handlechildren([C|_], QpNb, ChildNb) :-
not(solved(QpNb,ChildNb)),
once(meta_execute_qp(C)), fail.
handlechildren([_|Cs], QpNb, ChildNb) :-
ChildNb1 is ChildNb + 1,
handlechildren(Cs, QpNb, ChildNb1).
all_solved(QpNb, ChildNb, TotCs) :-
(ChildNb = TotCs -> true
; ChildNb1 is ChildNb + 1,
solved(QpNb, ChildNb1),
all_solved(QpNb, ChildNb1, TotCs)
).