Reputation: 29
I'm first in prolog.
There are some family tree. So I want to abstract one's aunt list but, if I use if,else than only one aunt is abstracted. And, If i don't use condition, than mom also abstracted from predicates.
How can I continue in if, else?
female(mgrandmother).
female(mom).
female(sis).
female(aunt1).
female(aunt2).
male(mgrandfather).
male(dad).
male(bro).
male(uncle1).
male(uncle2).
parent(mom,sis).
parent(dad,sis).
parent(mom,bro).
parent(dad,bro).
parent(mgrandmother,aunt1).
parent(mgrandfather,aunt1).
parent(mgrandmother,aunt2).
parent(mgrandfather,aunt2).
parent(mgrandmother,mom).
parent(mgrandfather,mom).
aunt(X,Y):-
parent(Z,Y), female(Z), parent(T, Z), male(T), repeat,parent(T,K),not(parent(K,Y))->X=K.
//If I printout all of aunts using like below
aunt(X,Y):-
parent(Z,Y), female(Z), parent(T, Z), male(T), repeat,parent(T,K),not(parent(K,Y))->X=K.
//Than, It'll be print out also mom
Upvotes: 1
Views: 73
Reputation: 477617
I think you make it more complicated than it is, by writing all logic in the aunt/2
predicate. Instead of trying to solve the entire problem in a single predicate, it is typically beneficial to write several small reusable predicates. It makes predicates easier to understand, and furthermore you can reuse these components in other predicates.
For example we can implement a slibing/2
predicate:
sibling(S1, S2) :-
parent(P, S1),
male(P),
parent(P, S2),
dif(S1, S2).
here the dif/2
will prevent that the slibings S1
and S2
are the same person. This thus means that we will not need to worry about that scenario in all use cases of the slibing/2
predicate. We here use male/1
to prevent that two siblings will be yielded two times: one time for the mother relation, and one time for the father relation.
Perhaps you want to later refine the above predicate, since this predicate will succeed if S1
and S2
are half-siblings given they have the father in common.
Next we can implement a sister/2
predicate for example:
sister(S, C) :-
sibling(S, C),
female(S).
Now our aunt/2
is simply the sister of the parent of a person, so:
aunt(A, C):-
parent(P, C),
sister(A, P).
Not only are the predicates way simpler, we now have two extra predicates. Furthermore if the logic of sibling/2
turns out to have some problems, we can fix it at that specific level, and all callers of sibling/2
will be fixed as well.
Upvotes: 2
Reputation: 1316
You probably mean "extract", not "abstract".
Why are you using repeat
? Did someone tell you to use it or you think you have to? Same with ->
: you certainly don't need it here.
Here is one way to define what you want:
aunt(Aunt, Child) :-
parent(Parent, Child),
siblings(Parent, Aunt),
female(Aunt).
siblings(C1, C2) :-
dif(C1, C2),
parent(P, C1),
parent(P, C2).
The only addition to what you have is dif/2
in the definition of siblings/2
, so that a person is not a sibling to themselves.
You will get answers on backtracking (you don't need to use repeat
!):
?- aunt(Aunt, Child).
Aunt = aunt1,
Child = sis ;
Aunt = aunt2,
Child = sis ;
Aunt = aunt1,
Child = sis ;
Aunt = aunt2,
Child = sis ;
Aunt = aunt1,
Child = bro ;
Aunt = aunt2,
Child = bro ;
Aunt = aunt1,
Child = bro ;
Aunt = aunt2,
Child = bro ;
false.
The easy way to show all solutions and avoid duplicates is setof/3
:
?- setof(Aunt-Child, aunt(Aunt, Child), Results).
Results = [aunt1-bro, aunt1-sis, aunt2-bro, aunt2-sis].
Upvotes: 2