java - 来自 Apache Jena 框架的推理示例的问题

标签 java rdf jena reasoning jena-rules

我有一个严重的问题来启动和运行任何推理机。 还有文档中的示例:https://jena.apache.org/documentation/inference/ 在这里不起作用。 我将示例转移到单元测试中,这样问题可能更容易重现。

推理是否仅限于某些环境,如空间 JDK 等,还是我弄错了什么?

谢谢

这里是示例代码(作为 java 单元测试):

import static org.junit.Assert.assertNotNull;
import java.io.PrintWriter;
import java.util.Iterator;

import org.junit.Before;
import org.junit.Test;

import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.reasoner.Derivation;
import com.hp.hpl.jena.reasoner.rulesys.GenericRuleReasoner;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
import com.hp.hpl.jena.vocabulary.RDFS;

public class ReasonerTest {

    String NS = "urn:x-hp-jena:eg/";

    // Build a trivial example data set
    Model model = ModelFactory.createDefaultModel();
    InfModel inf;

    Resource A = model.createResource(NS + "A");
    Resource B = model.createResource(NS + "B");
    Resource C = model.createResource(NS + "C");
    Resource D = model.createResource(NS + "D");

    Property p = model.createProperty(NS, "p");
    Property q = model.createProperty(NS, "q");


    @Before
    public void init() {

        // Some small examples (subProperty)
        model.add(p, RDFS.subPropertyOf, q);
        model.createResource(NS + "A").addProperty(p, "foo");

        String rules = "[rule1: (?a eg:p ?b) (?b eg:p ?c) -> (?a eg:p ?c)]";
        GenericRuleReasoner reasoner = new GenericRuleReasoner(Rule.parseRules(rules));
        reasoner.setDerivationLogging(true);
        inf = ModelFactory.createInfModel(reasoner, model);

        // Derivations
        A.addProperty(p, B);
        B.addProperty(p, C);
        C.addProperty(p, D);
    }


    @Test
    public void subProperty() {
        Statement statement =  A.getProperty(q);
        System.out.println("Statement: " + statement);
        assertNotNull(statement);
    }


    @Test
    public void derivations() {
        String trace = null;
        PrintWriter out = new PrintWriter(System.out);
        for (StmtIterator i = inf.listStatements(A, p, D); i.hasNext(); ) {
            Statement s = i.nextStatement();
            System.out.println("Statement is " + s);
            for (Iterator id = inf.getDerivation(s); id.hasNext(); ) {
                Derivation deriv = (Derivation) id.next();
                deriv.printTrace(out, true);
                trace += deriv.toString();
            }
        }
        out.flush();
        assertNotNull(trace);
    }

    @Test
    public void listStatements() {
        StmtIterator stmtIterator = inf.listStatements();
        while(stmtIterator.hasNext()) {
            System.out.println(stmtIterator.nextStatement());
        }
    }
}

最佳答案

前缀 eg: 不是你想的那样:

eg:规则中的前缀不会扩展到您认为的那样。我将您的规则字符串修改为

String rules = "[rule1: (?a eg:p ?b) (?b eg:p ?c) -> (?a eg:p ?c)] [rule2: -> (<urn:ex:a> eg:foo <urn:ex:b>)]";

因此 rule2 将始终将三元组 urn:ex:a eg:foo urn:ex:b 插入到图中。然后,测试的输出包括:

[urn:ex:a, urn:x-hp:eg/foo, urn:ex:b]
[urn:x-hp-jena:eg/C, urn:x-hp-jena:eg/p, urn:x-hp-jena:eg/D]

第一行显示我的 rule2 插入的三元组,而第二行使用您手动输入的前缀。我们看到 eg:前缀是 urn:x-hp:eg/ 的缩写.如果相应地更改 NS 字符串,请使用 String NS = "urn:x-hp:eg/"; ,那么您的推导测试将通过。

你需要问正确的模型

subProperty 测试失败有两个原因。首先,它正在检查错误的模型。

您正在检查 A.getProperty(q) :

Statement statement =  A.getProperty(q);
System.out.println("Statement: " + statement);
assertNotNull(statement);

A是您为模型创建的资源 model ,不是模型 inf ,所以当你要求 A.getProperty(q) , 它实际上是在问 model对于语句,因此您不会在 inf 中看到推论.您可以使用 inModel得到A “在 inf 中”所以 getProperty寻找正确的模型:

Statement statement = A.inModel(inf).getProperty(q);

或者,您也可以询问 inf直接是否包含 A q <something> 形式的三元组:

inf.contains( A, q, (RDFNode) null );

或者您可以枚举所有这样的语句:

StmtIterator stmts = inf.listStatements( A, q, (RDFNode) null );
assertTrue( stmts.hasNext() );
while ( stmts.hasNext() ) { 
  System.out.println( "Statement: "+stmts.next() );
}

你也需要RDFS推理

即使您正在查询正确的模型,您的推理模型仍然需要执行 RDFS 推理以及使属性 p 具有传递性的自定义规则。为此,我们可以从 RDFS 推理机中提取规则,将您的规则添加到该列表的副本中,然后使用新的规则列表创建自定义推理机:

// Get an RDFS reasoner
GenericRuleReasoner rdfsReasoner = (GenericRuleReasoner) ReasonerRegistry.getRDFSReasoner();
// Steal its rules, and add one of our own, and create a
// reasoner with these rules
List<Rule> customRules = new ArrayList<>( rdfsReasoner.getRules() );
String customRule = "[rule1: (?a eg:p ?b) (?b eg:p ?c) -> (?a eg:p ?c)]";
customRules.add( Rule.parseRule( customRule ));
Reasoner reasoner = new GenericRuleReasoner( customRules );

完整结果

这里是修改后的代码,全部放在一起方便复制和粘贴。所有测试均通过。

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.reasoner.Derivation;
import com.hp.hpl.jena.reasoner.Reasoner;
import com.hp.hpl.jena.reasoner.ReasonerRegistry;
import com.hp.hpl.jena.reasoner.rulesys.GenericRuleReasoner;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
import com.hp.hpl.jena.vocabulary.RDFS;

public class ReasonerTest {

    String NS = "urn:x-hp:eg/";

    // Build a trivial example data set
    Model model = ModelFactory.createDefaultModel();
    InfModel inf;

    Resource A = model.createResource(NS + "A");
    Resource B = model.createResource(NS + "B");
    Resource C = model.createResource(NS + "C");
    Resource D = model.createResource(NS + "D");

    Property p = model.createProperty(NS, "p");
    Property q = model.createProperty(NS, "q");


    @Before
    public void init() {

        // Some small examples (subProperty)
        model.add(p, RDFS.subPropertyOf, q);
        A.addProperty(p, "foo" );

        // Get an RDFS reasoner
        GenericRuleReasoner rdfsReasoner = (GenericRuleReasoner) ReasonerRegistry.getRDFSReasoner();
        // Steal its rules, and add one of our own, and create a
        // reasoner with these rules
        List<Rule> customRules = new ArrayList<>( rdfsReasoner.getRules() );
        String customRule = "[rule1: (?a eg:p ?b) (?b eg:p ?c) -> (?a eg:p ?c)]";
        customRules.add( Rule.parseRule( customRule ));
        Reasoner reasoner = new GenericRuleReasoner( customRules );

        reasoner.setDerivationLogging(true);
        inf = ModelFactory.createInfModel(reasoner, model);

        // Derivations
        A.addProperty(p, B);
        B.addProperty(p, C);
        C.addProperty(p, D);
    }

    @Test
    public void subProperty() {
        StmtIterator stmts = inf.listStatements( A, q, (RDFNode) null );
        assertTrue( stmts.hasNext() );
        while ( stmts.hasNext() ) { 
            System.out.println( "Statement: "+stmts.next() );
        }
    }

    @Test
    public void derivations() {
        String trace = null;
        PrintWriter out = new PrintWriter(System.out);
        for (StmtIterator i = inf.listStatements(A, p, D); i.hasNext(); ) {
            Statement s = i.nextStatement();
            System.out.println("Statement is " + s);
            for (Iterator<Derivation> id = inf.getDerivation(s); id.hasNext(); ) {
                Derivation deriv = (Derivation) id.next();
                deriv.printTrace(out, true);
                trace += deriv.toString();
            }
        }
        out.flush();
        assertNotNull(trace);
    }

    @Test
    public void listStatements() {
        StmtIterator stmtIterator = inf.listStatements();
        while(stmtIterator.hasNext()) {
            System.out.println(stmtIterator.nextStatement());
        }
    }
}

关于java - 来自 Apache Jena 框架的推理示例的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24786035/

相关文章:

java - 我们什么时候应该实现 Serializable 接口(interface)?

java - 如何知道使用 Runtime.exec() 执行的命令是给出一些输出还是只是等待而不给出任何输出?

xml - 是否可以使用 xsd 数据类型(例如 xsd :string) and xml language attribute simultaneously in OWL2/RDF?

rdf - 将多个文件增量数据加载到耶拿

java - 将 Json-Ld 对象数组读入 Apache Jena 中的模型。如何从模型中检索单个对象?

java - 耶拿 TDB : Nested Transactions

java - 我应该使用 ArrayList.clear() 还是创建一个新列表?

java - 如何内联抛出异常的方法?

odata - OData与语义Web/链接数据的比较

rdf - 命名法 : parametrized classes in RDF graphs