我有一个语义网络,具有以下层次结构:
Person: has body = true
Man: is a Person, height = 170
Sport Star: is a Man, height = 190
然后我想创建这些实例,例如:
Mark: is a Sport Star
然而,当我打电话,例如height(Mark, X)
我得到X = 170
,并需要按;
得到X = 190
。有没有办法直接获得190
?
您表示正在使用的SWI-Prolog对语义Web技术有广泛的支持。但是,如果您的语义网络仅包含is-a层次关系,您还可以使用Logtalk轻松表达它们,Logtalk可以与SWI-Prolog和大多数Prolog系统一起运行,使其具有广泛的可移植性:
% Person: has body = true
:- object(person).
:- public(has/1).
has(body).
:- end_object.
% Man: is a Person, default height = 170
:- object(man, extends(person)).
:- public(height/1).
height(170).
:- end_object.
% Sport Star: is a Man, default height = 190
:- object(sport_star, extends(man)).
% override inherited height
height(190).
:- end_object.
% Mark: is a Sport Star
:- object(mark, extends(sport_star)).
:- end_object.
% Spencer: is another Sport Star, but slim
:- object(spencer, extends(sport_star)).
% override inherited height
height(165).
:- end_object.
该解决方案使用原型层次结构。样本调用(确定性;无虚假选择点):
?- mark::height(Height).
Height = 190.
?- mark::has(What).
What = body.
?- spencer::height(Height).
Height = 165.
您可以根据需要创建任意数量的原型,可以在源文件中定义,也可以在运行时动态创建。例如。
?- create_object(alan, [extends(man)], [], []).
true.
?- alan::height(Height).
Height = 170.
如果您需要区分抽象和这些抽象的具体示例,也可以使用类而不是原型。
Paulo Moura的答案是Prolog扩展和库的可能性的一个很好的例子。如果您正在构建一个实际的应用程序,那么最好使用类似的东西。但是,如果你正在学习Prolog而你想知道它是如何工作的,这里还有一个纯粹的Prolog答案。
您观察到的行为与您的知识库一致,这允许两种可能的解释:Mark是一个人,因此他的身高是170,或者Mark是一个运动员,因此他的身高是195.两者都是有效的推导,由知识库,因此Prolog依次返回每一个。
您可以对规则施加额外限制,以便在遇到第一个事实时立即停止派生。然后将规则表述为“X的高度是X类事物的基本事实,或者,如果没有基本事实,则遵循isa关系并再次尝试”。这要求基本事实得到的另一个名称不是规则。没有任何部分可以用否定运算符\+
表示。
码:
% isa: general facts
isa(father,man).
isa(man,person).
% isa: specific facts
isa(mark,sportsman).
% height: general facts
height_base(person,170).
height_base(sportsman,195).
% height: rules
height(X,H) :- height_base(X,H).
height(X,H) :- \+height_base(X,_), isa(X,T), height(T,H).
查询:
?- height(man,X).
X = 170 ;
false.
?- height(mark,X).
X = 195 ;
false.
?- height(sportsman,X).
X = 195 ;
false.
?- height(person,X).
X = 170 ;
false.