How to avoid duplicate return values

I’m using: SWI-Prolog version 7.2.3

I want the code to: Return values which are not duplicates

But what I’m getting is: Duplicate values

My code looks like this:

parent(patch,spot).
parent(patch, fluffy).
parent(fang,spot).
parent(patch,tommy).
parent(fang,tommy).
parent(kitty,ranger).
parent(fairy,fang).
parent(frodo,fang).
parent(frodo,kitty).

/* CREATE A RULE FOR FINDING SIBLINGS - this returns the same value twice if the child cat has two shared parents */
sibling(A,B):-
	parent(C,A),
	parent(C,B),
	not(A=B).

See this StackOverflow answer: Select unique elements in Prolog

@EricGT Using setof/3 to hide identical solutions is a bad idea in the general case. You should avoid generating them, if possible, instead of generating them, then aggregating them, then throwing them away.

In this case, setof/3 doesn’t help anyway: the solutions are equivalent but they are not equal, so sorting does nothing.

In this particular case, you could replace not(A=B) with A @< B, for example.

@rflook You are using an ancient version of SWI-Prolog :slight_smile:

There are roughly two options. One is improve your logic to avoid double solutions. If you consider
(A.B) and (B,A) as the same, use A @> B instead of not(A=B) (which you better write as
\+ A = B or even better as A \= B). The other is to use SWI-Prolog’s distinct/1,2. This is SWI-Prolog specific. setof/3 and member also do the job, but compute all results before returning the first. Distinct/1,2 requires a newer version though.

1 Like