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:
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(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
appearancewhich 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
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
is true, whilst
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
charles were plugged in, both
ContB would be set to
european_animal, and so Prolog would return
true. Prolog would tell us that
wilbert are not of the same continent because
ContB would be set to different values (