views:

48

answers:

2

Hi everybody, first off thanks for helping. I am writing a prolog program describing family relationships, including all versions of in-laws. The logic is all there, what I need help with is some prolog problems as I am not very experienced with it. I am trying to set up multiple possibilities for each rule through use of semicolons.

The way I am treating in-laws is so that my brother in law is also my brother, so I need multiple checks to see which is true. I want prolog to return true, and only true, if any of the options are true. However, it returns true and false as possible options, since of course one of the options is always going to be false and the other is always going to be true. Either they are my brother in law, or my natural brother. I cant get prolog to return true only, and not have the option of false as another answer. If anyone has any advice it would be great. Relevant code is included below. So, if I type "brother(baby,dad)." I get true and false as possible answers when all I want is false. However, "brother(dad,baby)." only returns true. But I am rambling now. Sorry if any of the code is confusing with the baby dad stuff. Thanks!

/*facts for relationships*/

female(widow).
female(redhair).

spouse(i,widow).
spouse(widow,i).
spouse(dad,redhair).
spouse(redhair,dad).

child(i,dad).
child(redhair,widow).
child(baby,i).
child(onrun,dad).

male(onrun).
male(baby).
male(dad).
male(i).

/*rules*/
daughter(D,P):-
    female(D), (child(D,P);(spouse(P,S),child(D,S))).
son(D,P):-
    male(D), (child(D,P);(spouse(P,S),child(D,S))).
mother(X,Y):-
    female(X),
    child(Y,X).
father(X,Y):-
    male(X),
    child(Y,X).
son_in_law(C,P):-
    male(C),spouse(C,S),
    (child(S,P);(spouse(P,W),child(S,W))).
daughter_in_law(C,P):-
    female(C),spouse(C,S),
    (child(S,P);(spouse(P,W),child(S,W))).
brother(S1,S2) :- male(S1), 
    (child(S1,P) = child(S2,P2));
    (child(S1,P),child(S2,P2),spouse(P,P2));
    ((child(S1,P),son_in_law(S2,P));(child(S2,P),son_in_law(S1,P))).
A: 

thanks for reading. I know its not the easiest to understand. child is above in the set of facts that you see. Child doubles for a test to get parents. So when I pass in brother(baby, dad) the program then calls child(baby,X)=child(dad,X) the child function is being given the child, so it returns the parent. I then check to see if the parents are the same, as that would mean that the two are brothers.

cliff259
I can see what you're trying to do, but this isn't the way Prolog works. `child(S1,P) = child(S2,P2)` tries to unify two structures, which means that S1 and S2 should be equal.
larsmans
ahhh yes. So to achieve my purpose in this case I really want to test P = P2 after I use each function. This will test if the Parents are the same.
cliff259
But as I look more into negation from your previous pointer, I take it to mean that I could use negation to create the function brother() so that It will return true if the goal is proven true at any point? Basically, the result I want.
cliff259
+1  A: 

These multiple answers can be preventing with the meta-predicate once/1:

?- once(brother(baby,dad)).
true.

?-
larsmans
Thanks larsmans, just wanted to say for anyone else looking that this did the trick. I think I was over complicating things. A brief summary for anyone interested, I thought that my program was returning true as the first answer, and then when I asked for any other possible answers it returned false as a possible answer. In reality I now think that it was telling me that true was the answer, and when I asked for more possible answers it failed in finding any more answers and so returned false. This meta-predicate fixes that problem by only searching once, as I understand it. Thanks!
cliff259