Java 早期打印模型会在以后更改打印的表示形式吗?

Java 早期打印模型会在以后更改打印的表示形式吗?,java,jena,jena-rules,Java,Jena,Jena Rules,我在Jena 2.5.5(Linux上)中得到了一个奇怪的效果,我在那里玩推理API。下面的代码是一个精简版本。我正在创建一个初始为空的模型和一个通用规则推理器。我为某个语句添加了一个自反性规则。我将推理器附加到模型以获得一个模型。然后创建匹配语句并将其添加到模型中 结果:InfModel同时包含语句及其反面。到目前为止还不错,这就是它应该做的 现在,在将匹配语句添加到模型之前,当我System.out.println()InfModel时,结果完全不同:规则似乎不会触发,因此InfModel最

我在Jena 2.5.5(Linux上)中得到了一个奇怪的效果,我在那里玩推理API。下面的代码是一个精简版本。我正在创建一个初始为空的模型和一个通用规则推理器。我为某个语句添加了一个自反性规则。我将推理器附加到模型以获得一个模型。然后创建匹配语句并将其添加到模型中

结果:InfModel同时包含语句及其反面。到目前为止还不错,这就是它应该做的

现在,在将匹配语句添加到模型之前,当我
System.out.println()
InfModel时,结果完全不同:规则似乎不会触发,因此InfModel最终将不包含原始语句的相反部分

将模型写入控制台如何改变代码的功能?这种行为有记录吗

import java.util.*;

import com.hp.hpl.jena.rdf.model.*;
import com.hp.hpl.jena.reasoner.rulesys.*;

/**
 * Describe class <code>RuleTest</code> here.
 */
public class RuleTest {
    public static void main(String[] args) throws Exception {
        /* create model */
        Model model = ModelFactory.createDefaultModel();

        /* output model */
        System.out.println("original model : " + model);
        System.out.println("-----");

        /* collect rules */
        List<Rule> rules = new ArrayList<Rule>();
        Rule rule = Rule.parseRule("[ (subject predicate object) -> (object predicate subject) ].");
        rules.add(rule);

        /* create rule reasoner */
        GenericRuleReasoner reasoner = new GenericRuleReasoner(rules);

        /* attach reasoner to model */
        InfModel infModel = ModelFactory.createInfModel(reasoner, model);

        /* output model */
        //-----------------------------------------------//
        // commenting the following line in/out changes  //
        // the output of (*) below in Jena 2.5.5 ?!?!?!  //
        //-----------------------------------------------//
        //System.out.println("inference model: " + infModel);        
        System.out.println("=====");

        /* add facts to original model */
        Resource s = model.createResource("subject");
        Property p = model.createProperty("predicate");
        RDFNode  o = model.createResource("object");
        Statement stmt = model.createStatement(s, p, o);
        model.add(stmt);

        /* output models */
        System.out.println("original model : " + model);
        System.out.println("-----");
        System.out.println("inference model: " + infModel); // (*)
    }
}

很可能model.toString()有副作用。我还没有查看JENA源代码,所以我不能确定。

快速查看了相关源代码,您似乎有两个选择:

  • 如果要对基础模型进行更改,然后确保它们传播到infModel,则必须在进行更改之后以及在“询问”infModel之前调用infModel.rebind()

  • 您可以直接使用infModel(而不是model)来创建和添加语句的元素和语句本身


我知道这并不能直接回答您的问题,但它可能会解决您的问题(顺便说一句,这似乎是由ModelCom中的toString()方法触发的具体化引起的,该方法是InfModel的父类)。

几年后的今天,Jena出现在2.10.x系列中。注释掉指示行后,程序的输出为:

original model : <ModelCom   {} | >
-----
=====
original model : <ModelCom   {subject @predicate object} |  [subject, predicate, object]>
-----
inference model: <ModelCom   {object @predicate subject; subject @predicate object} |  [object, predicate, subject] [subject, predicate, object]>
当您这样做时,您将在两种情况下获得相同的输出。评论这句话时:

original model : <ModelCom   {} | >
-----
=====
original model : <ModelCom   {subject @predicate object} |  [subject, predicate, object]>
-----
inference model: <ModelCom   {object @predicate subject; subject @predicate object} |  [object, predicate, subject] [subject, predicate, object]>
original model : <ModelCom   {} | >
-----
inference model: <ModelCom   {} | >
=====
original model : <ModelCom   {subject @predicate object} |  [subject, predicate, object]>
-----
inference model: <ModelCom   {object @predicate subject; subject @predicate object} |  [object, predicate, subject] [subject, predicate, object]>
原始型号:
-----
=====
原始型号:
-----
推理模型:
在未注释行的情况下:

original model : <ModelCom   {} | >
-----
=====
original model : <ModelCom   {subject @predicate object} |  [subject, predicate, object]>
-----
inference model: <ModelCom   {object @predicate subject; subject @predicate object} |  [object, predicate, subject] [subject, predicate, object]>
original model : <ModelCom   {} | >
-----
inference model: <ModelCom   {} | >
=====
original model : <ModelCom   {subject @predicate object} |  [subject, predicate, object]>
-----
inference model: <ModelCom   {object @predicate subject; subject @predicate object} |  [object, predicate, subject] [subject, predicate, object]>
原始型号:
-----
推理模型:
=====
原始型号:
-----
推理模型:
我的猜测是,编写InfModel的字符串表示不会导致执行任何推断,除非尚未执行任何推断,然后打印基础模型,然后打印推断出的任何其他三元组。因此:

  • 在第一种情况下(仅打印一次
    infModel
    ),它还没有进行任何推断,因此它参考
    model
    ,进行适当的推断,并获得额外的三元组。然后打印模型的三元组和推断的三元组
  • 在第二种情况下(当您打印两次
    infModel
    时),第一次打印
    infModel
    时,它参考
    model
    并进行一些推断,但是
    model
    为空,因此没有额外的三元组,然后它打印
    model
    的三元组和额外推断的三元组(没有)。然后,第二次打印
    infModel
    时,推理已经执行,因此它打印
    model
    的三元组(但有一个额外的三元组)和任何推断的三元组(没有,因为没有执行更多的推理)

将三元组添加到
model
后调用
rebind()
,这意味着在第二种情况下,额外的推断三元组在打印时可用。

感谢您的回答-我认为toString()不仅“可能”,而且完全明显地具有副作用。这当然出乎意料,但也许我和耶拿在一起的经历太少,不知道发生了什么。在任何情况下,我都找不到关于这种行为的任何文档。