问题描述:

Consider the following simple program:

h(n0).

h(p(A,N)) :- (A=a, h(N)) ; (A=b , h(N)).

Query:

1 ?- h(p(A,N)).

A = a,

N = n0 ;

A = a,

N = p(a, n0) ;

A = a,

N = p(a, p(a, n0)) ;

A = a,

N = p(a, p(a, p(a, n0))) ;

A = a,

N = p(a, p(a, p(a, p(a, n0)))) ;

...

Since the first disjunct [(A=a, h(N))] produces infinite number of answers it cannot show the answers produced by the second disjunct [(A=b , h(N))].

The question is:

Is it possible to change the code so that on the query, it alternates between the solutions from the first disjunct and the second one?

网友答案:

To get a fair listing of the results of h/1 you can use an auxiliary predicate, say h2/2 that consists of two goals: 1) A predicate pairs/1 that is only describing the the structure of your solution without concrete values:

pairs(n0).
pairs(p(A,N)) :-
   pairs(N).

And yields the following answers:

   ?- pairs(X).
X = n0 ? ;
X = p(_A,n0) ? ;
X = p(_A,p(_B,n0)) ? ;
X = p(_A,p(_B,p(_C,n0))) ? 
...

2) Your predicate h/1 as the second goal that describes what the variables _A, _B, _C,... actually are:

h2(X) :-
   pairs(X),
   h(X).

If you query this predicate you get the desired results:

   ?- h2(X).
X = n0 ? ;
X = p(a,n0) ? ;
X = p(b,n0) ? ;
X = p(a,p(a,n0)) ? ;
X = p(a,p(b,n0)) ? ;
X = p(b,p(a,n0)) ? ;
X = p(b,p(b,n0)) ? ;
X = p(a,p(a,p(a,n0))) ? ;
...

Note, how the first goal pairs/2 is producing your nested pair-structure one pair at a time. Then the second goal, your original predicate, is producing all possible combinations of a's and b's for that very pair. Then h/2 is backtracking to the next pair produced by pairs/2. And so on.

相关阅读:
Top