%% This Prolog file demonstrates some of the intricacies of writing even %% a simple Prolog predicate if we want to suppress redundant solutions. %% It works in Sicstus Prolog but you may beed to modify the module %% code or include your own definition of member/2 to get it to work in %% other PRologs %% we need the member/2 predicate from the lists library. :- use_module(library(lists)). %% some data to experiment with. parent(homer,bart). parent(marge,bart). male(bart). parent(homer,lisa). parent(marge,lisa). female(lisa). parent(homer,maggie). parent(marge,maggie). female(maggie). %% sib1 is a simple definition of the sibling/2 relation. Two people are %% siblings if they share a common parent. You can't be your own sibling. sib1(X,Y) :- parent(P,X), parent(P,Y), \+X=Y. %% But maybe we don't want duplicate answers in q query result stream. %% sib2 tries to use a cut to prevent redundant proofs, but at the expense %% of being able to use the predicate to generate pairs of siblings. sib2(X,Y) :- parent(P,X), parent(P,Y), (\+X=Y), !. %% sib3 tries this in a more principled way, using setof/3 to generate a %% *set* of pairs of siblings, and then returning members of the set, once %% at a time. sib3(X,Y) :- setof((X,Y), P^(parent(P,X),parent(P,Y), \+X=Y), Sibs), member((X,Y), Sibs). %% But we know that sibling is a symmetric relation. Maybe we only want %% each pair only once. sib4 adds an ordering constraint on the values %% in the pair. Unfortunately, this means we can no,longer solve %% sib4(maggie,X). sib4(X,Y) :- setof((X,Y), P^(parent(P,X),parent(P,Y), X@