【发布时间】:2014-05-21 10:17:24
【问题描述】:
我正在使用 OWL 规则在 JENA 做一个项目。
在我的本体中,我有一个名为 PEGI_RATING 的实体。一个PEGI_RATING 可以有多个描述符。
例子:
<http://localhost:2020/PEGI_RATING/6>
a vocab:PEGI_RATING ;
rdfs:label "PEGI_RATING #6" ;
vocab:PEGI_RATING_age
16 ;
vocab:PEGI_RATING_has_PEGI_CONTENT_DESCRIPTOR
<http://localhost:2020/PEGI_CONTENT_DESCRIPTOR/Online> ,
<http://localhost:2020/PEGI_CONTENT_DESCRIPTOR/Violence> ,
<http://localhost:2020/PEGI_CONTENT_DESCRIPTOR/Bad_Language> ;
vocab:PEGI_RATING_ratingId
6 .
现在,我想在 OWL 中编写一个规则,为每个 PEGI_RATING 附加一个年龄。我知道它已经存在,但需要证明我知道如何使用推理器。
现在,内容描述符附加了一个年龄。我按照以下规则执行此操作:
[AgeLimit:
(?descr rdf:type vocab:PEGI_CONTENT_DESCRIPTOR)
(?descr vocab:PEGI_CONTENT_DESCRIPTOR_contentDescriptor "Sex")
->
(?descr vocab:PEGI_CONTENT_DESCRIPTOR_inf_age_limit "16"^^xsd:integer)
]
所以最后我有一个VIDEO_GAME,它有一个PEGI_RATING id。
示例:
<http://localhost:2020/VIDEOGAME/Grand_Theft_Auto_IV>
a vocab:VIDEOGAME ;
rdfs:label "VIDEOGAME #Grand Theft Auto IV" ;
vocab:VIDEOGAME_EsrbRatingCategoryCategory
<http://localhost:2020/ESRB_RATING_CATEGORY/M> ;
vocab:VIDEOGAME_gameplayRulesGameplayRulesId
<http://localhost:2020/GAMEPLAY_RULES/3> ;
vocab:VIDEOGAME_has_SIDE_GOAL
<http://localhost:2020/SIDE_GOAL/Complete_all_missions.> ;
vocab:VIDEOGAME_onlineMultiplayer
"false"^^xsd:boolean ;
vocab:VIDEOGAME_pegiRatingRatingId
<http://localhost:2020/PEGI_RATING/3> ;
vocab:VIDEOGAME_summary
"For Niko Bellic, fresh off the boat from Europe, it is the hope he can escape his past. For his cousin, Roman, it is the vision that together they can find fortune in Liberty City, gateway to the land of opportunity. As they slip into debt and are dragged into a criminal underworld by a series of shysters, thieves and sociopaths, they discover that the reality is very different from the dream in a city that worships money and status, and is heaven for those who have them and a living nightmare for those who don't." ;
vocab:VIDEOGAME_title
"Grand Theft Auto IV" .
我想创建一个规则来确定附加到VIDEOGAME 的PEGI_RATING 的PEGI_CONTENT_DESCRIPTORs 的最大年龄。
在 Prolog 中我会这样做:
[Age:
(?gameRelease rdf:type vocab:GAME_RELEASE)
(?gameRelease vocab:GAME_RELEASE_videogameTitle ?game)
(?game vocab:VIDEOGAME_pegiRatingRatingId ?pegiID)
(?pegiID vocab:PEGI_RATING_has_PEGI_CONTENT_DESCRIPTOR ?descriptor)
(?descriptor vocab:PEGI_CONTENT_DESCRIPTOR_inf_age_limit ?age)
(?descriptor vocab:PEGI_CONTENT_DESCRIPTOR_inf_age_limit ?age2)
not(lessThan(?age, ?age2))
->
(?game vocab:VIDEOGAME_inf_minimumAge ?age)]
但由于 OWL 似乎没有因失败而否定,所以我不知道如何解决它。
到目前为止,我已经尝试了以下规则但没有成功:
[Age:
(?gameRelease rdf:type vocab:GAME_RELEASE)
(?gameRelease vocab:GAME_RELEASE_videogameTitle ?game)
(?game vocab:VIDEOGAME_pegiRatingRatingId ?pegiID)
(?pegiID vocab:PEGI_RATING_has_PEGI_CONTENT_DESCRIPTOR ?descriptor)
(?descriptor vocab:PEGI_CONTENT_DESCRIPTOR_inf_age_limit ?age)
(?descriptor vocab:PEGI_CONTENT_DESCRIPTOR_inf_age_limit ?age2)
greaterThan(?age, ?age2)
->
(?game vocab:VIDEOGAME_inf_minimumAge ?age)]
最终结果
所以最后我们有了一个工作函数。它确实做了应该做的事情。不过..
首先,我们有许多 Jena 格式的规则,它们为每个 PEGI_CONTENT_DESCRIPTOR 添加了一个特定的年龄。这纯粹是出于教学原因(即,表明我们可以使用推理器)。这行得通。当我添加这些规则时,我可以对我的模型执行 SPARQL 查询并获得正确的值。当我写我的模型时(正如 Rob Hall 在他的例子中指出的那样)PEGI_CONTENT_DESCRIPTORs 确实有一个年龄。它们看起来像这样:
<http://local.host.com:2020/PEGI_CONTENT_DESCRIPTOR/Violence>
a vocab:PEGI_CONTENT_DESCRIPTOR ;
rdfs:label "PEGI_CONTENT_DESCRIPTOR #Violence" ;
vocab:PEGI_CONTENT_DESCRIPTOR_contentDescriptor
"Violence" ;
vocab:PEGI_CONTENT_DESCRIPTOR_explanation
"May contain scenes of people getting injured or dying, often by use of weapons, whether realistically or in a fantastical or cartoonish manner. Also may contain gore and blood-letting." ;
vocab:PEGI_CONTENT_DESCRIPTOR_inf_age_limit
18 .
请记住,视频游戏的 PEGI 评级 ID:?game vocab:VIDEOGAME_pegiRatingRatingId ?pegiId。
我们要执行 Jena Builtin 如下:
minimumPegiAge(?pegiID, ?age)
为此,我们有以下功能。它确实有效。然而,出于某种奇怪的原因,context.find(pegiID, has_descriptor.asNode(), Node.ANY); 似乎没有迭代两个特定的PEGI_DESCRIPTORs。即Sex和Violence。如前所述,它们存在于推断模型中,并且是从 SPARQL 查询返回的。我们可以处理一个错误吗?还是我们错过了什么?
final Property has_age_limit =
ResourceFactory.createProperty("http://localhost:2020/vocab/PEGI_CONTENT_DESCRIPTOR_inf_age_limit");
final Property has_descriptor =
ResourceFactory.createProperty("http://localhost:2020/vocab/PEGI_RATING_has_PEGI_CONTENT_DESCRIPTOR");
// Create and Register a Builtin for Jena's rule system.
BuiltinRegistry.theRegistry.register(new BaseBuiltin() {
@Override
public String getName() {
return "minPegiAge";
}
@Override
public boolean bodyCall(final Node[] args, final int length, final com.hp.hpl.jena.reasoner.rulesys.RuleContext context) {
checkArgs(length, context);
final Node pegiID = getArg(0, args, context);
if( !getArg(1, args, context).isVariable() ){
return false;
}
// Should get all the descriptors for this PegiID.
ClosableIterator<Triple> x = context.find(pegiID, has_descriptor.asNode(), Node.ANY);
// Iterate over them.
final Iterator<Node> results =
new NiceIterator<Triple>()
.andThen(x) // Get all the descriptors
.mapWith(new Map1<Triple,Node>(){
@Override
public Node map1(Triple o) {
// o is a triple
// These triples are descriptors
// We need to get the age for these descriptors
System.out.println(o);
return o.getObject();
}});
if( !results.hasNext() ) {
return false;
}
Node min = null;
while(results.hasNext()) {
final Node pegiContentDescriptor = results.next();
System.out.println("DESCRIPTION: " + pegiContentDescriptor.toString());
ClosableIterator<Triple> y = context.find(pegiContentDescriptor, has_age_limit.asNode(), Node.ANY);
// Iterate over them.
final Iterator<Node> singleAge =
new NiceIterator<Triple>()
.andThen(y) // Get all the descriptors
.mapWith(new Map1<Triple,Node>(){
@Override
public Node map1(Triple o) {
// o is a triple
// These triples are descriptors
// We need to get the age for these descriptors
return o.getObject();
}});
if (singleAge.hasNext()) {
Node age = singleAge.next();
System.out.println("AGE: " + age.getLiteralValue());
if (min == null) {
min = age;
} else {
if (Util.compareTypedLiterals(min, age) < 0) {
min = age;
}
}
}
}
if (min == null) {
System.out.println("GEEN MINIMUM AGE GEVONDEN!");
} else {
System.out.println("MINIMUM: " + min.getLiteralValue());
}
context.getEnv().bind(getArg(1, args, context), min);
return true;
}
});
// Load TTL-file (full db dump!)
// Note: make sure the path containing the ttl file does not contain strange characters :D
// "-" and maybe spaces are not allowed
model = ModelFactory.createDefaultModel();
model.read(getClass().getResourceAsStream("/trivial-mapping-dump.ttl"), null, "TURTLE");
// Load the rules.
List<Rule> rules = Rule.rulesFromURL(getClass().getResource("/rules.txt").toString());
// Let the reasoner.. reason!
// Then add the triples existing due to rule firings to our base graph
GenericRuleReasoner r = new GenericRuleReasoner(rules);
r.setOWLTranslation(true); // not needed in RDFS case
r.setTransitiveClosureCaching(true);
r.setMode(GenericRuleReasoner.HYBRID);
InfModel infmodel = ModelFactory.createInfModel(r, model);
model.add(infmodel.getDeductionsModel());
}
【问题讨论】:
-
小提示:您提供的规则采用 Jena 语法。它们本身并不在“猫头鹰”中。
-
是的,我真的不知道有什么区别。 Afaik 我可以编写猫头鹰规则,但他们只需要遵守这个特定的语法吗?对吗?
-
这些规则将特定于 Apache Jena。还有其他规则语法(如 SWRL)。您选择的语法反映了将在幕后解释它们的推理器。 OWL 推理是通过使用 Jena 规则在 Jena 中实现的。这个推理是基于通用 RDF 数据的。如果您编写一个新的 Jena 规则并将其添加到包含 OWL 规则的规则集中,那么您将使用 owl 和您的额外规则进行推理。规则本身不会附加到您的文档中,也不会以猫头鹰的形式表达。这是一个小词汇,不会影响问题的答案。
-
感谢您的详细说明!我很感激!
-
关于您的编辑:您执行内置命令的规则是否已更改?我在 Jena 中遇到过似乎是一个错误,如果我的内置函数是我的规则正文中的第一个子句,那么我的上下文显示为空。我还会看看你当前的实现。
标签: jena owl jena-rules