I am reading the book "Prolog and Natural-Language Analysis" (pdf) by Pereira and Shieber and I got stuck on a remark in Problem 2.7 which reads:
In semantic network representations, we often want to ask [...] “What relationships hold between Ford and the class of companies?”
Modify your representation of semantic networks to allow both this new kind of question and the kind in the previous problem. HINT: Treat semantic network relations as Prolog individuals. This is an important Prolog programming technique, sometimes called reification in philosophical circles.
I am not familiar with this reification
technique.
OK, let's assume this database of facts and rules:
isa('Ole Black', 'Mustangs').
isa('Lizzy', 'Automobiles').
isa('Ford','Companies').
isa('GM','Companies').
isa('1968','Dates').
ako('Model T', 'Automobiles').
ako('Mustangs', 'Automobiles').
ako('Companies', 'Legal Persons').
ako('Humans', 'Legal Persons').
ako('Humans', 'Physical Objects').
ako('Automobiles', 'Physical Objects').
ako('Legal Persons', 'Universal').
ako('Dates', 'Universal').
ako('Physical Objects', 'Universal').
have_mass('Physical Objects').
self_propelled('Automobiles').
company(X) :- isa(X,'Companies').
legal_persons(X) :- ako(X,'Legal Persons').
How do I write a query that, in the code above finds that the relationship between 'Ford'
and 'Companies'
is isa
?
Of course I could always write something like
fact(isa, 'Ford','Companies').
and query ?- fact(X, 'Ford','Companies').
but somehow I do not think that this is the right way to do it.
Can anybody explain me how to do it properly?
Combining aspects of both Paul's and Carlo's answers, another possible solution is to introduce a meta-relation predicate. For example:
relation(isa/2).
relation(ako/2).
relation(have_mass/1).
...
This avoids loosing the benefit of first-argument indexing for some of the queries using the original database because of the reification of relations. It also avoids, in Carlo's solution, the call to current_predicate/2
picking up e.g. auxiliary predicates that should not be considered.
With the definition above of the relation/2
predicate, we can write:
relation(Relation, Entity1, Entity2) :-
relation(Relation/2),
call(Relation, Entity1, Entity2).
relation(Relation, Entity) :-
relation(Relation/1),
call(Relation, Entity).
and then query:
?- relation(Relation, 'Ford', 'Companies').
Relation = isa.
I'd like to add a little bit of background to the previous answers (which are very helpful).
As far as I can tell, there's no generally accepted defintion for reification in Prolog. One could say that the relationships in your original code are already partly reified. Examples:
isa('Ford', 'Companies').
% ...is a reification of...
company('Ford').
ako('Companies', 'Legal Persons').
% ...is a reification of...
legal_person(X) :- company(X).
have_mass('Physical Objects').
% ...is a reification of...
has_mass(X) :- physical_object(X).
self_propelled('Automobiles').
% ...is a reification of...
self_propelled(X) :- automobile(X).
See the Reification section in Notes on Semantic Nets and Frames by Matthew Huntbach for details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With