【问题标题】:Problems with inference examples from Apache Jena framework来自 Apache Jena 框架的推理示例问题
【发布时间】:2014-07-16 16:30:30
【问题描述】:

我有一个严重的问题要启动和运行任何推理器。 还有文档中的示例: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());
        }
    }
}

【问题讨论】:

    标签: java rdf jena reasoning jena-rules


    【解决方案1】:

    前缀 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/";,那么您的 derivations 测试将通过。

    您需要询问合适的型号

    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 "in inf" 以便 getProperty 查找正确的模型:

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

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

    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());
            }
        }
    }
    

    【讨论】:

    • 嘿,很好的答案。即使我意识到命名空间存在问题,您的回答也澄清了很多。老实说,我仍在尝试添加 RDFS 推理但失败了。我补充说: Reasoner reasoner = RDFSRuleReasonerFactory.theInstance().create(null); reasoner.setParameter(ReasonerVocabulary.PROPsetRDFSLevel, ReasonerVocabulary.RDFS_DEFAULT); reasoner.setDerivationLogging(true); inf = ModelFactory.createInfModel(reasoner, model);但它并不能解决问题。你有什么想法,这可能有什么问题?
    • 甚至比我意识到匹配存在问题抱歉,但我不太清楚你的意思。这对你有用吗?
    • 我的意思是,有一个名称空间不匹配,例如在一侧和“urn:x-hp-jena:eg/”在另一侧。您是否有一个指针可以在哪里找到有关您在第一句话中提到的名称空间扩展的更多信息?
    • The documentation“为了保持规则可读,URI refs 支持 qname 语法。已知前缀集是使用 PrintUtil 对象注册的前缀。这最初知道 rdf、rdfs、 owl、xsd 和一个 test 命名空间,例如,但是可以在 java 代码中注册更多映射。此外,还可以在规则文件中定义额外的前缀映射,见下文。" 它没有说明 @987654347 @ 映射到虽然。我在这里只是通过实验发现的。一些示例显示“urn:x-hp:eg”,其他示例显示“urn:x-hp-jena:eg”。
    • 好的,再次感谢。但是,如果您知道如何启动和运行推理,我会非常满意。正如第一条评论中提到的,将 RDFSReasoner 与 RDFS 规则一起使用并不是诀窍。
    猜你喜欢
    • 2014-09-22
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    相关资源
    最近更新 更多