Search code examples
prologgnu-prolog

Mutually exclusion in a logic task


There is three friends - misha, petya, vova. Surnames: ivanov, semyonov, gerasimov.

name(misha).
name(vova).
name(petya).
surname(ivanov).
surname(semyonov).
surname(gerasimov).

misha isn't gerasimov.

full_name(misha,X) :- 
surname(X),
X \= gerasimov.  

vova is studying in the 6th grade. gerasimov is in the 5th. How to define surnames (several) of vova?

The father of vova is an engineer, the father of ivanov is a locksmith.

father(vova,ingeneer).
father(ivanov,locksmith).

How to define surname (one) of vova?


Solution

  • First we need to capture the fact that each name has one of the given surnames.

    is_one_of(Name, [ivanov, semyonov, gerasimov]) :-
        member(Name, [misha, vova, petya]).
    

    We are also given characteristics (studying, father) about names and surnames, each one with different values. This is captured by the following predicates.

    name_characteristic(vova, studying, sixth_grade).
    name_characteristic(vova, father, ingeneer).
    
    surname_characteristic(gerasimov, studying, fifth_grade).
    surname_characteristic(ivanov, father, locksmith).
    

    We are also given that gerasimov is_not the surname of misha.

    is_not(misha, gerasimov).
    

    Rule 1: Name cannot have Surname if for some common characterictic, their values are different.

    is_not(Name, Surname) :-
        name_characteristic(Name, Characteristic, Value1),
        surname_characteristic(Surname, Characteristic, Value2),
        Value1 \= Value2.
    

    Rule 2: Name must have Surname if none of the other possible surnames is the surname of Name.

    is_(Name, Surname) :-
        is_one_of(Name, Surnames),
        select(Surname, Surnames, RemainingSurnames),
        is_none_of(Name, RemainingSurnames).
    
    is_none_of(_, []).
    is_none_of(Name, [Surname | RemainingSurnames]) :-
        is_not(Name, Surname),
        is_none_of(Name, RemainingSurnames).
    

    Querying for is(vova, Surname) yields:

    Surname = semyonov
    

    Querying for is_not(Name, Surname) yields:

    Name = misha,
    Surname = gerasimov
    
    Name = vova,
    Surname = gerasimov
    
    Name = vova,
    Surname = ivanov