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.
我在Jena 2.5.5(在Linux上)得到了一个奇怪的效果,我正在使用推理API。以下代码是精简版本。我正在创建一个最初为空的模型和一个通用的规则推理器。我为某个陈述添加了反身性规则。我将推理器附加到模型以获得InfModel。然后我创建匹配语句并将其添加到模型中。
Result: InfModel contains both the statement and its reverse. So far so good, that's what it's supposed to do.
结果:InfModel包含语句及其反向。到目前为止这么好,这就是应该做的。
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.
现在,当我在向Model添加匹配语句之前的System.out.println()InfModel时,结果完全不同:规则似乎没有触发,因此,InfModel最终不会包含原始语句的反向。
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); // (*)
}
}
3 个解决方案
#1
1
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.
如果您想对基本模型进行更改,然后确保它们传播到infModel,那么您必须在进行更改之后和“询问”infModel之前调用infModel.rebind()。
-
You can use the infModel directly (instead of model) to create and add the statement's elements and the statement itself.
您可以直接使用infModel(而不是模型)来创建和添加语句的元素和语句本身。
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).
我知道这不能直接回答你的问题,但它可以解决你的问题(顺便说一下,似乎是由ModelCom中的toString()方法触发的具体化 - InfModel的父类)。
#2
0
It's likely that model.toString() has side-effects. I have not looked at the JENA source, so I can't be sure, though.
model.toString()可能有副作用。我没有看过JENA的来源,所以我不能确定。
#3
0
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:
现在几年后,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]>
and the string representation of the InfModel contains two triples. When the line is uncommented, the output is:
并且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]>
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.)
并且InfModel的第二个字符串表示只有一个三元组,因此仍然可以观察到差异。 (我在这里列出了输出,因为在问题中不清楚观察到了什么差异。)
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:
简短的回答是,这种情况发生的原因是你在偷偷摸摸地修改模型而没有告诉infModel你改变了底层模型。要解决此问题,您应该添加对infModel.rebind()的调用;更新模型后。也就是说,你现在拥有:
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:
我的猜测是,写入InfModel的字符串表示不会导致执行任何推断,除非尚未执行推理,然后打印基础模型,然后打印任何推断的三元组。结果是:
- In the first case (when you print
infModel
just once) it hasn't done any inference yet, so it consultsmodel
and does the appropriate inference and gets the additional triples. Then it printsmodel
's triples and then the inferred triples. - In the second case (when you print
infModel
twice), the first time you printinfModel
, it consultsmodel
and does some inference, butmodel
is empty, so there are no additional triples, and then it printsmodel
's triples and the additional inferred triples (there are none). Then, the second timeinfModel
is printed, inference has already been performed, so it printsmodel
's triples (but there's an extra one) and any inferred triples (there are none, because no more inference was performed).
在第一种情况下(当您只打印一次infModel时)它还没有进行任何推断,因此它会参考模型并进行适当的推理并获得额外的三元组。然后它打印模型的三元组,然后打印推断的三元组。
在第二种情况下(当你打印infModel两次时),第一次打印infModel时,它会参考模型并做一些推理,但是模型是空的,所以没有额外的三元组,然后它打印模型的三元组和额外推断的三元组(没有了)。然后,第二次打印infModel,已经执行了推理,因此它打印模型的三元组(但是有一个额外的)和任何推断的三元组(没有,因为不再执行推理)。
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.
在将三元组添加到模型之后调用rebind()意味着在第二种情况下,在打印时可以使用额外的推断三元组。
#1
1
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.
如果您想对基本模型进行更改,然后确保它们传播到infModel,那么您必须在进行更改之后和“询问”infModel之前调用infModel.rebind()。
-
You can use the infModel directly (instead of model) to create and add the statement's elements and the statement itself.
您可以直接使用infModel(而不是模型)来创建和添加语句的元素和语句本身。
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).
我知道这不能直接回答你的问题,但它可以解决你的问题(顺便说一下,似乎是由ModelCom中的toString()方法触发的具体化 - InfModel的父类)。
#2
0
It's likely that model.toString() has side-effects. I have not looked at the JENA source, so I can't be sure, though.
model.toString()可能有副作用。我没有看过JENA的来源,所以我不能确定。
#3
0
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:
现在几年后,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]>
and the string representation of the InfModel contains two triples. When the line is uncommented, the output is:
并且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]>
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.)
并且InfModel的第二个字符串表示只有一个三元组,因此仍然可以观察到差异。 (我在这里列出了输出,因为在问题中不清楚观察到了什么差异。)
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:
简短的回答是,这种情况发生的原因是你在偷偷摸摸地修改模型而没有告诉infModel你改变了底层模型。要解决此问题,您应该添加对infModel.rebind()的调用;更新模型后。也就是说,你现在拥有:
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:
我的猜测是,写入InfModel的字符串表示不会导致执行任何推断,除非尚未执行推理,然后打印基础模型,然后打印任何推断的三元组。结果是:
- In the first case (when you print
infModel
just once) it hasn't done any inference yet, so it consultsmodel
and does the appropriate inference and gets the additional triples. Then it printsmodel
's triples and then the inferred triples. - In the second case (when you print
infModel
twice), the first time you printinfModel
, it consultsmodel
and does some inference, butmodel
is empty, so there are no additional triples, and then it printsmodel
's triples and the additional inferred triples (there are none). Then, the second timeinfModel
is printed, inference has already been performed, so it printsmodel
's triples (but there's an extra one) and any inferred triples (there are none, because no more inference was performed).
在第一种情况下(当您只打印一次infModel时)它还没有进行任何推断,因此它会参考模型并进行适当的推理并获得额外的三元组。然后它打印模型的三元组,然后打印推断的三元组。
在第二种情况下(当你打印infModel两次时),第一次打印infModel时,它会参考模型并做一些推理,但是模型是空的,所以没有额外的三元组,然后它打印模型的三元组和额外推断的三元组(没有了)。然后,第二次打印infModel,已经执行了推理,因此它打印模型的三元组(但是有一个额外的)和任何推断的三元组(没有,因为不再执行推理)。
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.
在将三元组添加到模型之后调用rebind()意味着在第二种情况下,在打印时可以使用额外的推断三元组。