0

I write prolog program as below. Now, when I run halfsister predicate as halfsister(X,Y). I got result

X = ann
Y = sylvia ? ;

X = sylvia
Y = ann ? ;

but both are the same result but showing twice. How can I make the program to show the same result for once only? my prolog code:

parent(john,ann).
parent(jim,john).
parent(jim,keith).
parent(mary,ann).
parent(mary,sylvia).
parent(brian,sylvia).
male(keith).
male(jim).
male(brian).
female(sylvia).
female(ann).
female(marry).
female(john).
brother(X,Y):-parent(Z,X),parent(Z,Y),male(X),X\==Y.
uncle(X,Y):-brother(X,Z),parent(Z,Y).
halfsister(X,Y):-
    parent(A,X),
    parent(A,Y),
    parent(B,X),
    parent(C,Y),
    \+(A = B),
    \+(A = C),
    \+(B = C),
    female(Y).

Thanks for your valuable, time.

Rakibul Islam
  • 325
  • 1
  • 3
  • 13
  • Can wrap in https://www.swi-prolog.org/pldoc/doc_for?object=distinct/1 – brebs Mar 08 '22 at 06:41
  • Thanks for your comment. I'm not still getting how to use it in my code section. I'm learning Prolog. – Rakibul Islam Mar 08 '22 at 08:14
  • Oops, the X and Y values are switching around, rather than being shown twice, so distinct won't help. Instead, add e.g. a final condition "X @> Y" to the end of halfsister/2, for symmetry-breaking as explained at https://stackoverflow.com/questions/28047637/prolog-keep-getting-false-result – brebs Mar 08 '22 at 08:25
  • It is much safer to use "dif(A, B)" instead of "\+(A = B)", to be reliable with non-ground variables, as per https://stackoverflow.com/questions/13757261/using-2-or-dif-2 – brebs Mar 08 '22 at 08:33
  • "both are the same result" - No, they are not the same result. – Enigmativity Mar 08 '22 at 09:49
  • Actually, I think a better answer than my earlier comments is to say that the "duplicate" answer given by Prolog in the OP is correct as-is, because X and Y are different people. As mentioned, can use @> or @< to break symmetry when appropriate. – brebs Mar 08 '22 at 15:05

1 Answers1

4
  1. I don't think it is necessary to eliminate this "duplication", because the predicate halfsister(X,Y) means "Y is X's half sister". You got two answers, one means "sylvia is ann's half-sister", the other means "ann is sylvia's half-sister". So there is nothing wrong here.

  2. If you insist on eliminating them, you can try:

    halfsister(X,Y):-
        parent(A,X),
        parent(A,Y),
        parent(B,X),
        parent(C,Y),
        \+(A = B),
        \+(A = C),
        \+(B = C),
        female(Y),
        (   female(X)
        ->  X @< Y
        ;   true
        ).
    

    Query:

    ?- halfsister(X,Y).
    X = ann,
    Y = sylvia ;
    false.
    
chansey
  • 1,266
  • 9
  • 20
  • 1
    There is no advantage to using -> ( https://www.swi-prolog.org/pldoc/man?predicate=-%3E/2 ) here. – brebs Mar 08 '22 at 10:00
  • @brebs I used `->` because it may be exist `male`. For example, adding facts `parent(mary,zed). parent(john,zed). male(zed).` If do not use `(female(X) -> X @< Y ; true)`, the `X = zed, Y = sylvia` will not be in the answers. – chansey Mar 08 '22 at 10:14
  • I agree that using `->` is usually not a good idea. – chansey Mar 08 '22 at 10:15
  • "X @> Y" is sufficient, for symmetry-breaking. Adding -> just risks breaking soundness. – brebs Mar 08 '22 at 11:06
  • @brebs Try to add facts `parent(mary,aaron). parent(john,aaron). male(aaron).`. Then do the query `?- halfsister(X,Y).`, aaron won't be in the answers if only using `X @> Y`. However, sylvia is apparently aaron's half sister. – chansey Mar 08 '22 at 11:19
  • You're contorting the logic with "female(X) -> X @< Y; true" to become unreliable due to the "; true" alternative. – brebs Mar 08 '22 at 12:43
  • @brebs What's the problem, can you give an example? – chansey Mar 08 '22 at 12:50
  • As an example (this will probably show with awful formatting) of how the "; true" alternative affects: ?- member(A, [1, 2, 3]), (A > 2 -> A > 1 ; true). A = 1 ; A = 2 ; A = 3. – brebs Mar 08 '22 at 13:29
  • 1
    @brebs I don't understand what you mean. What I mean is that (1) what's the problem of using `->` in this family example? (2) as we know that Prolog is a pragmatic programming language, it is not necessary to keep all predicates logic pure as long as it get our jobs done. Here I just treat X and Y as two output variables. – chansey Mar 08 '22 at 13:45
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/242727/discussion-between-brebs-and-chansey). – brebs Mar 08 '22 at 14:05
  • After a great discussion, the purpose of the -> here is to remove the symmetry when both X and Y are half-sisters of each other. Could be perhaps more intuitively expressed as: (male(X) -> true ; X <@ Y). – brebs Mar 08 '22 at 15:11