0

Here is my code, just focus on the 3 last rules:

father(costac,anne). 
mother(mary,mike). 
husband(costac,mary). 
sex_male(costac). 
sex_male(mike). 
sex_female(mary). 
sex_female(anne). 


mother(X,Y):-
        father(Z,Y),
        wife(X,Z).
father(X,Y):-
        mother(Z,Y),
        husband(X,Z).
husband(X,Y):-
        wife(Y,X).
wife(X,Y):-
        husband(Y,X).
husband(X,Y):-
        father(X,Z),
        mother(Y,Z).
wife(X,Y):-
        father(Y,Z),
        mother(X,Z).
brother(X,Y):-
        father(Z,Y),
        father(Z,X),
        sex_male(X),
        \+ X = Y.
brother(X,Y):-
        mother(Z,Y),
        mother(Z,X),
        sex_male(X),
        \+ X = Y.

sister(X,Y):-
        father(Z,X),
        sex_female(X),
        father(Z,Y),
        \+ X = Y.
sister(X,Y):-
        mother(Z,X),
        sex_female(X),
        mother(Z,Y),
        \+ X = Y.

find_rel(Ans):-
        write('Please give first name: '), read(X),
        find(X,Ans).
find(X,Ans):-
        write('Would you like to give second name? -yes/no-'), nl, read(Ask), find_ans(Ask,X,Ans).
find_ans(yes,X,Ans):-
        write('Please give second name: '), read(Y),nl,
        (father(X,Y),!, Ans = father(X,Y));
        (mother(X,Y), !,Ans = mother(X,Y));
        (husband(X,Y), !,Ans = husband(X,Y));
        (wife(X,Y), !,Ans = wife(X,Y));
        (brother(X,Y), !,Ans = brother(X,Y));
        (sister(X,Y), Ans = sister(X,Y)).
/*find_ans(no,X,Ans):-....*/

I don't care for any of the other answers, just the answert to this question:

?-find_rel(Ans).

Giving names costac & anne, I do get what I want, cause it's the first line of my rule. Everything else I try fails and give the title's ERROR! I tried using cut, but nothing worked. When I trace, for example I give mary & mike, what i see is that even if it goes to the step (mother(X,Y), !,Ans = mother(X,Y)); and produce mother(mary,anne) ignores it, and goes to the next two and keep looping that thing :

   Call: (10) father(mary, mike) ? creep
   Call: (11) mother(_G1479, mike) ? creep
   Exit: (11) mother(mary, mike) ? creep
   Call: (11) husband(mary, mary) ? creep
   Call: (12) wife(mary, mary) ? creep
   Call: (13) husband(mary, mary) ? creep
   Call: (14) wife(mary, mary) ? creep
   Call: (15) husband(mary, mary) ? creep
   Call: (16) wife(mary, mary) ? creep
   Call: (17) husband(mary, mary) ? creep
   Call: (18) wife(mary, mary) ? creep
   Call: (19) husband(mary, mary) ? creep
   Call: (20) wife(mary, mary) ? creep
   Call: (21) husband(mary, mary) ? 
false
  • 10,264
  • 13
  • 101
  • 209
  • I would like to give a string(Ans) back to the user, that returns `father(coctac, anne)` if the input of X, Y is costac, anne. –  Nov 17 '15 at 14:14
  • I see, OK. I thought you were making a common mistake. :) – lurker Nov 17 '15 at 14:15
  • haha, thanks for your help anyway! :) I'm not sure if that's the right or optimal way to do it, i'm just following an example on our slides and I can't find something similar on the internet unfortunately. –  Nov 17 '15 at 14:20
  • There are probably scores of posts on Stackoverflow.com for these family relationship problems. They are often plagued with the same issue: circular logic. The reason being that there are multiple ways of defining the same family relationship, and sometimes the circular logic is hidden in rules that come back around to the same point. First order of business: you should group your rules/facts by the same name (Prolog warns about this - you have a `wife` clause between two `husband`s - not good). Then look for such redundant cycles and try to define relationships via "one direction". – lurker Nov 17 '15 at 14:41
  • Another example: since you already have `wife(X, Y) :- husband(Y, X)` do you really need the other rule for `wife(X, Y)`? I think it may be redundant. If you remove that, it might get rid of the cycle. The cuts don't help here because the cycle is occurring within a call before the cut. In addition, if you find you need to add cuts to get rid of problems, then there's something wrong with the code. Cuts are not for fixing problems. They're for defining specific logical requirements. :) – lurker Nov 17 '15 at 14:45
  • That's true, what I've noticed is, that even if i delete everything in the final rule and let it like this: `find_ans(yes,X,Ans):- write('Please give second name: '), read(Y),nl, (father(X,Y), Ans = father(X,Y)); (mother(X,Y),Ans = mother(X,Y)).` and give as input mary & mike, it keep looping with husband and wife, so probably the problem is somewhere else in the upper rules as you said. –  Nov 17 '15 at 14:54
  • The other rule for wife exists because our teacher asked us to cover everything so that if he adds something in the knowledge base, our rules will cover it. –  Nov 17 '15 at 15:05
  • I still think the rule is redundant. If your `husband` rule is comprehensive, then `wife(X, Y) :- husband(Y, X)` should always be adequate. If `husband` isn't complete, you can complement with `wife(X, Y)` but then would need to be careful about cyclic overlap. – lurker Nov 17 '15 at 16:14

0 Answers0