1
votes

How can you define mother/father/sister/brother relationships such that asserting sister(bart, maggie) makes ?- female(maggie) evaluate as true?

I'm working on a toy family relation problem. This is what I have:

parent(bart, homer).
parent(bart, marge).
parent(lisa, homer).
parent(lisa, marge).

male(homer).
male(bart).
female(marge).
female(lisa).

mother(X,Y) :- female(Y), parent(X,Y).
father(X,Y) :- male(Y), parent(X,Y).

sister(X,Y) :- female(Y), father(X,F), father(Y,F), mother(X,M), mother(Y,M), X/=Y.

I'd like to be able to do the following:

sister(bart, maggie).

?- female(maggie).
% expect yes

i.e. support the "common sense" definition where if you assert that maggie is bart's sister, we know that maggie is female, while still obtaining sister(bart, lisa) being true based on the parent/gender assertions I already have.

2
So write a rule to support that deduction. Note that if someone is both asserted to be female explicitly & asserted to be someone's sister, you'll have 2 ways of proving she is female.Scott Hunter

2 Answers

1
votes

As it is, your system expects male/female and parent to be a fact and derives father/mother/brother/sister through rules

You could do this:

% X is female if it is somebody's sister.
female(X) :- sister(_,X).

But combined with the other rule, it probably won't terminate (X is female if she is sb's sister, she is sb.'s sister if she is female...)

You could set different facts and rules to reverse this way of doing it, e.g. decide that basic facts are sister, mother, son, daughter... But you need to decide what forms elementary information in your database, and what forms derived information. If you want anything to be derived from anything, while staying with simple rules, you quickly end up with a system that doesn't terminate, exploring more and more ways to derive information that is already known.

If you want to have a richer set of inference rules (e.g. if X implies Y and Y is false, then X is false), and make sure your process terminates, doesn't give you the result multiple times, etc, you need to write (or borrow) your own rule interpreter, that is, your own inference engine.

1
votes

Common sense reasoning is in general way too complex to implement for any general purpose programming language. For this very limited domain, we can prototype in SWI-Prolog a simple minded metainterpreter that generalize the goal selection from rules body, and avoids loops by means of tabling:


:- autoload(library(tabling)).
:- table solve/1, rule/2.

solve(F) :-
    rule(F,[]).
solve(H) :-
    rule(H,B),
    solve_b(B).

% allowed builtins
solve(X\=Y) :- X\=Y.

solve_b([]).
solve_b(B) :-
    select(G,B,R),
    solve(G),
    solve_b(R).

rule(parent(bart, homer), []).
rule(parent(bart, marge), []).
rule(parent(lisa, homer), []).
rule(parent(lisa, marge), []).

rule(male(homer), []).
rule(male(bart), []).
rule(male(M), [father(_,M)]).
rule(male(M), [brother(_,M)]).

rule(female(marge), []).
rule(female(lisa), []).
rule(female(F), [mother(_,F)]).
rule(female(F), [sister(_,F)]).

rule(mother(X,Y), [female(Y), parent(X,Y)]).
rule(father(X,Y), [male(Y), parent(X,Y)]).

rule(sister(X,Y), [
         female(Y),
         sibling(X,Y)
     ]).
rule(brother(X,Y), [
         male(Y),
         sibling(X,Y)
     ]).

rule(sibling(X,Y), [
         father(X,F),
         father(Y,F),
         mother(X,M),
         mother(Y,M),
         X\=Y
     ]).
rule(sister(bart,maggie), []).