Semantic Nets in Prolog
Yesterday a few friends were puzzling over a few Prolog exam questions, and I thought I'd write up a post about what we learnt before I forget :-)
The first part of the question asked us to convert a paragraph of knowledge into a semantic net (isa / hasa) diagram. Here's the paragraph in question:
Charles and Wilbert are rats which are brown coloured European animals. Charles has a brown collar. Animals are defined as having DNA and being about to move. They include African animals, European animals and Australian animals. Skippy is a kangaroo; kangaroos are brown coloured Australian animals. Wallabies are dark brown Australian animals, Willy being one of them. They have a diet of eucalyptus leaves. Gnu are antelopes and come from Africa, and they have stripes, as are Nyala. Stella is a Gnu and Madge a Nyala.
This first part wasn't too tough. It doesn't quite fit in some places, but here's what I came up with:
(Generated using mermaid by Knut Sveidqvist)
The blue nodes are the isa
node, while the green nodes are the hasa
nodes. The next part asked us to convert the above into prolog. Again, this wasn't particularly hard - it's just a bunch of isa/2
's and hasa/2
's:
isa(charles, rat).
isa(wilbert, rat).
isa(rat, european_animal).
isa(european_animal, animal).
isa(african_animal, animal).
isa(australian_animal, animal).
isa(skippy, kangaroo).
isa(kangaroo, australian_animal).
isa(wallaby, australian_animal).
isa(willy, wallaby).
isa(gnu, antelope).
isa(antelope, african_animal).
isa(stella, gnu).
isa(madge, nyala).
hasa(animal, dna).
hasa(animal, able_to_move).
hasa(rat, colour(brown)).
hasa(wallaby, colour(dark_brown)).
hasa(wallaby, diet(eucaliptus_leaves)).
hasa(gnu, stripes).
hasa(nyala, stripes).
After converting the diagram into Prolog, we were then asked to write some Prolog that interacts with the above knowledge base. Here's the first challenge:
Define a predicate called
appearance
which behaves as follows:appearance(wilbert,Colour). Colour=dark_brown true. appearance(skippy,Colour). Colour=brown true.
Upon first sight, this looks rather complicated, but it's not actually as bad as it looks. Basically, it is asking for a predicate, that, given the name of a thing, returns the colour of that thing. For example, wilbert
was produce the answer brown
, and wallaby
would return dark_brown
. The trick here is to get Prolog to recurse up the isa hasa tree if it doesn't find the answer at the current node.
When thinking about recursion, a good idea is to consider the stopping condition first. In our case, we want it to stop when it finds a thing that has a colour. Here's that in Prolog:
appearance(Name, Colour) :-
hasa(Name, colour(Colour)).
Now we've got a stopping condition in place, we can think about the recursion itself. If it doesn't find a colour at the current node, we want Prolog to follow the appropriate isa
fact and travel to the next level up. We can do that like so:
appearance(Name, Colour) :-
isa(Name, Thing),
appearance(Thing, Colour).
That completes the first challenge. If you put the above together this is what you'll get:
appearance(Name, Colour) :-
hasa(Name, colour(Colour)).
appearance(Name, Colour) :-
isa(Name, Thing),
appearance(Thing, Colour).
The second challenge, however, was much more challenging:
Write a predicate that takes two argument and is true if both animals live on the same continent. Thus
?- same_continent(skippy,willy).
is true, whilst
?- same_continent(stella,skippy).
is not.
The problem with this challenge is that unlike the first challenge, there isn't any way (that I could think of anyway) to determine he continent that an animal comes from. I managed to hack around this by always going up 2 levels before comparing the things to see if they are the same:
same_continent(NameA, NameB) :-
isa(NameA, AnimalTypeA),
isa(AnimalTypeA, ContA),
isa(NameB, AnimalTypeB),
isa(AnimalTypeB, ContB),
ContA = ContB.
For example, if wilfred
and charles
were plugged in, both ContA
and ContB
would be set to european_animal
, and so Prolog would return true
. Prolog would tell us that skippy
and wilbert
are not of the same continent because ContA
and ContB
would be set to different values (european_animal
and australian_animal
).