理解具体化 - “x和y之间存在什么关系?”

10

我正在阅读Pereira和Shieber的书《Prolog and Natural-Language Analysis》(pdf),其中有一个问题2.7的备注让我卡住了,它说:

在语义网络表示中,我们经常想问[...]“Ford和公司类之间存在什么关系?”

修改您的语义网络表示,以允许这种新类型的问题和前面问题中的问题。提示:将语义网络关系视为Prolog个体。这是一种重要的Prolog编程技术,有时在哲学圈中称为具体化。

我不熟悉这种具体化技术。

好的,让我们假设这个事实和规则的数据库:

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').

如何编写一个查询,在上面的代码中找到'Ford''Companies'之间的关系是isa? 当然,我可以像这样写一些东西:
fact(isa, 'Ford','Companies').

我想查询?- fact(X, 'Ford','Companies').,但是我不认为这是正确的方法。

有人能解释一下如何正确地查询吗?


我该如何编写一个查询,在上面的代码中找到“Ford”和“Companies”之间的关系是isa?你的意思是要找到将它们“绑定”在一起的谓词吗? - A.A.
如果我正确理解“binding”的含义,那么我该如何找到绑定两个变量的谓词。 - acortis
我没有尝试过,但根据这个答案https://dev59.com/lF7Va4cB1Zd3GeqPIU33#8510861和你的查询,我猜以下代码可能有效:forall(fact(X, 'Ford', 'Companies'), writeln(X)) - jcsahnwaldt Reinstate Monica
...但是“修改你的语义网络表达”这部分听起来好像你不应该写这样的查询,而是应该改变数据结构...不知道怎么做... - jcsahnwaldt Reinstate Monica
2
@jcsahnwaldt 我认为他不想用那种方式解决它,难道没有一个可以打印出谓词的 SWI-Prolog 函数吗?我找了一下,但什么也没找到。 - A.A.
4个回答

6

结合Paul和Carlo的回答,另一个可能的解决方案是引入一个元关系谓词。例如:

relation(isa/2).
relation(ako/2).
relation(have_mass/1).
...

这避免了由于关系实例化而导致一些查询使用原数据库时失去第一个参数索引的好处。在卡罗的解决方案中,它也避免了调用current_predicate/2来挑选不应该被考虑的辅助谓词。通过上述对relation/2谓词的定义,我们可以编写如下代码:
relation(Relation, Entity1, Entity2) :-
    relation(Relation/2),
    call(Relation, Entity1, Entity2).

relation(Relation, Entity) :-
    relation(Relation/1),
    call(Relation, Entity).

然后进行查询:

?- relation(Relation, 'Ford', 'Companies').
Relation = isa.

我很喜欢这个,保罗!当你喜欢三个答案时,你会怎么做呢?!?!? - acortis
你可以随时将它们的想法结合起来,以适合你的应用程序的方式,并将结果提交为答案。 - Paulo Moura

5

我希望为之前的回答增加一些背景信息(这些回答非常有帮助)。

据我所知,在Prolog中,并没有被广泛接受的关于 具体化 的定义。你可以说,你原始代码中的关系已经部分地被具体化了。举例:

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).

详见《语义网络和框架笔记》中的具体化章节,作者是马修·亨特巴奇


4

不确定这个答案是否符合书本意图......我很多年前读过它的意大利语翻译版本,也不记得问题了。

在SWI-Prolog中,模块发挥着重要作用,因此我会选择:

:- module(so_relationships, [which_rel/3]).

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').

which_rel(A,B,R) :-
    current_predicate(so_relationships:R/2),
    C=..[R,A,B],
    %catch(call(C),E,(writeln(E),fail)).
    call(C).

注意 (被注释掉的) catch/3。在与模块名称限定谓词指示符之前是必需的。
?- which_rel('Ford','Companies',R).
R = isa ;
false.

2
C=..[R,A,B], call(C). ----> call(R,A,B). - Paulo Moura
很棒的答案!我喜欢它!请看一下我对保罗的评论。我喜欢我不必重新定义数据库中的事实。 - acortis
这些解决方案在你无法修改事实时非常好用,但它们是一种生成和测试算法,因此时间复杂度为O(n)。如果你能够具体化关系,那么它只是一个查找操作,通过索引可以达到O(1)的时间复杂度。 - Paul Brown

3

要从:

isa('Ford','Companies').

到:

fact(isa, 'Ford','Companies').

具体化技术是一种在Prolog中使用的技术。在Prolog中,functor必须是一个原子,就像你可能已经发现的查询一样:

?- HowRelated('Ford', 'Companies').
HowRelated = isa.

"would be invalid syntax"是无效的语法,Prolog中的谓词是抽象的,您无法直接推理它。要将其变成具体的内容,以便您可以进行推理,需要进行再生产。典型的排序顺序是(主题,谓词,对象):

fact('Ford', isa, 'Companies').

像这样查询:

?- fact('Ford', HowRelated, 'Companies').
HowRelated = isa.

一种Prolog实现(例如在评论中提到的SWI-Prolog)超越了第一参数索引,对于查找这种类型的查询非常快,并且您现在可以将事实的任何部分作为变量用于您的查询。请放心,这是正确的方法,也是RDF和OWL中所做的方式,其中谓词具有反身性或传递性等属性。

我没有针对您提供特定书籍参考,但是在PrologHub上有一篇博客文章"通过示例进行再现"


1
计算机科学中没有什么问题是不能通过增加另一层“解释”来解决的。 :) - Will Ness
谢谢Paul的回答,你为我澄清了具象化的概念,正是我所想的。然而,下面Carlo和Paulo的回答更接近我所想的解决方案,因为我不必重新定义我的事实数据库。 - acortis
你所想象的是一种线性时间的解决方法,而实际上存在一种常数时间的解决方案。要弄清楚'Mustangs'与'Universal'之间的关系,需要在当前数据库排序下进行9次查找。将你的事实改为三元组,无论它们的顺序如何,都只需要3次查找。即使是大型的事实数据库也可以通过脚本快速重新定义,并通过规则(同样由脚本编写)提供遗留访问。当你能够重新定义时,请这样做。 - Paul Brown

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接