[net.lang.prolog] Dave Plummer's bagof query

ramesh@edcaad.UUCP (Ramesh Krishnamurti) (08/20/86)

In reponse to Dave Plummer's query, the way bag_of(X,P,B) works 
in C-Prolog and hence (?) ought to in DEC-10 Prolog is to

find to all instances of X such that P is provable with the
condition that any variables in P not X are bound.

Thus for the program,

p(1,2).
p(1,1).
p(2,_).
p(3,_).
p(4,4).

bagof(X,p(X,Y),B) will, on backtracking, successively generate the lists

[3,2,1] with Y bound to 2
[1]     with Y bound to 1
[4]     with Y bound to 4

Ideally, it should produce the lists

[3,2,1] with Y bound to 2
[3,2,1] with Y bound to 1
[4,3,2] with Y bound to 4

But thats asking too much of Prolog !

If you want the variables in P not in X to remain free then
they must be explicitly bound by an existential quantifier ^.

That is,

bagof(X,Y^p(X,Y),B) will generate the list

[4,3,2,1,1] with Y bound to _

If you dont want to be bothered with specifying the free variables
the following version of bagof works. 

%----------------------------------------------------------------
bag(_,_,_):-		asserta($bag(base,_)),
			fail.
bag(X,P,B):-		Pred,
			asserta($bag(item,X)), 
			fail.
bag(_,_,B):-		$gather([],B).


$gather(C,B):-		retract($bag(Tag,X)),
			!,
			$gather(Tag,X,C,B).


$gather(base,_,B,B):-	!.
$gather(item,X,C,B):-	!, 
			$gather([X|C],B).
%----------------------------------------------------------------

However, for the database:

drinks(tom,lager).
drinks(dick,bitter).
drinks(harry,bitter).
drinks(bill,lager).
drinks(jack,lager).
drinks(bill,bitter).

bag(X,drinks(X,Y),B) will produce

B = [tom,dick,harry,bill,jack,bill] with Y bound to _

whereas 

bagof(X,drinks(X,Y),B) will successively produce

B = [jack,bill,tom]    with Y = lager
B = [bill,harry,dick]  with Y = bitter

Take your pick.

-- Ramesh

cdsm@doc.ic.ac.uk (Chris Moss) (08/22/86)

   
>>Date: Wed 6 Aug 86 14:38:43-CDT
>>From: Dave Plummer <ATP.PLUMMER@R20.UTEXAS.EDU>
>>Subject: DEC-10 Bagof - Bug?
>>
>>Given the program:
>>
>>p(1,_). p(2,_). p(3,3). p(4,4).
>>
>>and the goal bagof(X, p(X,Y), S).  Edinburgh DEC-10 Prolog
>>returns,
>>
>>S = [1,2,3] X = _ Y = 3
>>S = [4]     X = _ Y = 4
>>
>>This behaviour doesn't agree with my reading of the
>>documentation

Poplog produces the solutions:
	S=[4]  X =_1 Y=4
	S=[3]  X =_1 Y=3
	S=[1,2] X=_1 Y=_2

which is _slightly_ more consistent.
The problem has been dealt with in:
  Lee Naish: All solutions predicates in Prolog.
	Tech Report 84/4, Dept of Comp. Sc., Univ of Melbourne.
(it's been published I think, but I forget where)
He has a 'hard-line' solution which involves coroutining and
never returning variables if they can be subsequently bound.

Chris Moss.  cdsm@doc.ic.ac.uk cdsm@icdoc.uucp