YJS
YJS

Reputation: 29

How to abstract all datas using if else in prolog

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

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

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

User9213
User9213

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

Related Questions