提前打印 InfModel 会更改稍后打印的表示形式吗?

发布于 2024-07-09 07:46:46 字数 2162 浏览 14 评论 0原文

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

结果: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); // (*)
    }
}

I'm getting a strange effect in Jena 2.5.5 (on Linux) where I am playing around with the inference API. The following code is a stripped down version. I am creating an initially empty Model and a generic rule reasoner. I add a reflexivity rule for a certain statement. I attach the reasoner to the model to get an InfModel. Then I create the matching statement and add it to the Model.

Result: InfModel contains both the statement and its reverse. So far so good, that's what it's supposed to do.

Now, when I System.out.println() the InfModel prior to adding the matching statement to Model, the result is completely different: the rule seems not to fire and thus, InfModel will end up not containing the reverse of the original statement.

How does writing the model to the console change the functionality of the code? Is this behavior documented?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

樱桃奶球 2024-07-16 07:46:46

快速浏览一下相关源代码,您似乎有两个选择:

  • 如果您想对基本模型进行更改,然后确保它们传播到 infModel ,那么您必须在进行更改后、“询问”infModel 任何内容之前调用 infModel.rebind()

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

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

Had a quick look at the relevant source and it appears that you have two options:

  • If you want to make changes to the base model and then be sure that they propagate to the infModel, then you have to call infModel.rebind() after having made the changes and before you "ask" the infModel anything.

  • You can use the infModel directly (instead of model) to create and add the statement's elements and the statement itself.

I know this does not directly answer your question, but it may solve your problem (which, btw, seems to be caused by reification triggered by the toString() method in ModelCom - the parent class of InfModel).

八巷 2024-07-16 07:46:46

model.toString() 可能有副作用。 我没有看过 JENA 来源,所以我不能确定。

It's likely that model.toString() has side-effects. I have not looked at the JENA source, so I can't be sure, though.

梦中楼上月下 2024-07-16 07:46:46

现在已经是几年后的事了,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]>

并且 InfModel 的字符串表示形式包含两个三元组。 当该行取消注释时,输出为:

original model : <ModelCom   {} | >
-----
inference model: <ModelCom   {} | >
=====
original model : <ModelCom   {subject @predicate object} |  [subject, predicate, object]>
-----
inference model: <ModelCom   {subject @predicate object} |  [subject, predicate, object]>

InfModel 的第二个字符串表示只有一个三元组,因此仍然可以观察到差异。 (我在此处包含了输出,因为在问题中不清楚观察到什么差异。)

简短的答案是,发生这种情况是因为您偷偷摸摸地修改了模型< /code> 而不告诉 infModel 您更改了底层 model。 要解决此问题,您应该在更新 model 后添加对 infModel.rebind(); 的调用。 也就是说,您现在将拥有:

model.add(stmt);
infModel.rebind();

当您执行此操作时,您将在两种情况下获得相同的输出。 注释掉该行:

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 并进行适当的推理并得到额外的三元组。 然后它打印 model 的三元组,然后是推断的三元组。
  • 在第二种情况下(当您打印 infModel 两次时),第一次打印 infModel 时,它会查阅 model 并进行一些推理,但是 < code>model 为空,因此没有额外的三元组,然后它打印 model 的三元组和附加的推断三元组(没有)。 然后,第二次打印 infModel 时,已经执行了推理,因此它打印 model 的三元组(但有一个额外的)和任何推断的三元组(有没有,因为没有进行更多的推理)。

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

It's now a few years later and Jena is in the 2.10.x series. When the indicated line is commented out, the output of your program is:

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]>

and the string representation of the InfModel contains two triples. When the line is uncommented, the output is:

original model : <ModelCom   {} | >
-----
inference model: <ModelCom   {} | >
=====
original model : <ModelCom   {subject @predicate object} |  [subject, predicate, object]>
-----
inference model: <ModelCom   {subject @predicate object} |  [subject, predicate, object]>

and the second string representation of the InfModel has only one triple, so the difference is still observed. (I included the output here, because in the question it isn't clear what difference was being observed.)

The short answer is that this happens because you're being sneaky and modifying model without telling infModel that you changed the underlying model. To address this, you should add a call to infModel.rebind(); after you update model. That is, you would now have:

model.add(stmt);
infModel.rebind();

When you do this, you'll get the same output in both cases. With the line commented:

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]>

With the line uncommented:

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]>

My guess here is that writing the string representation of the InfModel doesn't cause any inference to be performed unless no inference has been performed yet, and then prints the underlying model and then any additional triples that are inferred. As a result:

  • In the first case (when you print infModel just once) it hasn't done any inference yet, so it consults model and does the appropriate inference and gets the additional triples. Then it prints model's triples and then the inferred triples.
  • In the second case (when you print infModel twice), the first time you print infModel, it consults model and does some inference, but model is empty, so there are no additional triples, and then it prints model's triples and the additional inferred triples (there are none). Then, the second time infModel is printed, inference has already been performed, so it prints model's triples (but there's an extra one) and any inferred triples (there are none, because no more inference was performed).

The call to rebind() after adding triples to model means that in the second case, the additional inferred triples are available at the time of printing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文