我正在使用 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" .
我想创建一个规则来确定PEGI_CONTENT_DESCRIPTOR
s 附加到 的PEGI_RATING
最大年龄VIDEOGAME
。
在 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_DESCRIPTOR
s 确实有一个年龄。它们看起来像这样:
<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_DESCRIPTOR
的 s。即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());
}