2

我正在使用 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_GAMEPEGI_RATINGid的。例子:

<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_DESCRIPTORs 附加到 的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_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 .

请记住,视频游戏具有 PE​​GI 评级 ID ?game vocab:VIDEOGAME_pegiRatingRatingId ?pegiId:。

我们要执行 Jena Builtin 如下:

minimumPegiAge(?pegiID, ?age)

为此,我们有以下功能。它确实有效。然而,出于某种奇怪的原因,context.find(pegiID, has_descriptor.asNode(), Node.ANY);似乎没有迭代两个特定PEGI_DESCRIPTOR的 s。即SexViolence。如前所述,它们存在于推断模型中,并且是从 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());

}
4

1 回答 1

2

这与现有问题非常相似:Giving array as parameter to jena builtin。在开始之前,请注意使用 SPARQL 查询识别此元素非常容易。

在 Jena 中,您可以实现类似于以下的规则:

[Age: 
  (?game urn:ex:hasRating ?pegiID) 
  minPegiAge(?pegiID ?age) 
  -> 
  (?game urn:ex:age ?age)]

开始编辑

非常重要的是,您的规则以一些通用的三元组模式开始,而不是从自定义内置函数(minPegiAge在这种情况下)开始。我遇到了一个问题,即RuleContext提供给我的内置函数的内容不从RuleContext#find(...). 此外,我的规则上下文的InfGraph(以及Graph)都是空图,与我的实际InfModel. 一旦规则更改为包含一些通用三元组模式作为起始模式,那么与您将返回的InfGraph关联的RuleContext就是相同的。InfGraphInfModel

结束编辑

这要求您随后实现 Jena Builtin来计算最小值。在 Builtin 中,您需要使用可用RuleContext的来探索您的图表并获得您需要探索的最少的东西。下面的示例创建一个内置函数,用于提取特定数据类型属性的最小值。

// These properties will be used in the example, I define them for
// convenience here.
final Property hasRating = ResourceFactory.createProperty("urn:ex:hasRating");
final Property age = ResourceFactory.createProperty("urn:ex:age");

// 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 RuleContext context) {
        checkArgs(length, context);
        final Node rating = getArg(0, args, context);
        if( !getArg(1, args, context).isVariable() ){
            return false;
        }

        final Iterator<Node> results = 
                new NiceIterator<Triple>()
                .andThen(context.find(rating, age.asNode(), Node.ANY))
                .mapWith(new Map1<Triple,Node>(){
                    @Override
                    public Node map1(Triple o) {
                        return o.getObject();
                    }});
        if( !results.hasNext() ) {
            return false;
        }

        Node min = results.next();
        while(results.hasNext()) {
            final Node val = results.next();
            if( Util.compareTypedLiterals(val, min) < 0 ) {
                min = val;
            }
        }
        context.getEnv().bind(getArg(1, args, context), min);
        return true;
    }

});

// Construct some sample data for this simplified version of
// your example scenario.
final Model rawData = ModelFactory.createDefaultModel();
final Resource game = rawData.createResource("urn:ex:theGame");
final Resource rating = rawData.createResource("urn:ex:theRating");
game.addProperty(hasRating, rating);
rating.addLiteral(age, 15);
rating.addLiteral(age, 14);

// Construct a simplified version of the rule that you use
// in order to identify when the minimum age needs to be
// detected.
final String rules = 
        "[Age: \n"+
        "  (?game urn:ex:hasRating ?pegiID) \n"+
        "  minPegiAge(?pegiID ?age) \n"+
        "  -> \n"+
        "  (?game urn:ex:age ?age)]";


final Reasoner reasoner;
try( final BufferedReader src = new BufferedReader(new StringReader(rules)) ) {
  reasoner = new GenericRuleReasoner(Rule.parseRules(Rule.rulesParserFromReader(src)));
}
final InfModel inf = ModelFactory.createInfModel(reasoner, rawData);

// Write the model, now including a minimum age triple associated with
// the game rather than the various pe
inf.write(System.out, "TTL");
于 2014-05-21T16:08:34.190 回答