2008-12-08 5 views
2

Je reçois un effet étrange dans Jena 2.5.5 (sur Linux) où je joue avec l'API d'inférence. Le code suivant est une version simplifiée. Je crée un modèle initialement vide et un raisonneur de règle générique. J'ajoute une règle de réflexivité pour une certaine déclaration. J'attache le raisonneur au modèle pour obtenir un InfModel. Ensuite, je crée l'instruction correspondante et l'ajoute au modèle. Résultat: InfModel contient à la fois l'instruction et son inverse. Jusqu'ici tout va bien, c'est ce qu'il est censé faire. Maintenant, quand je System.out.println() l'InfModel avant d'ajouter l'instruction correspondante à Model, le résultat est complètement différent: la règle semble ne pas se déclencher et ainsi, InfModel finira par ne pas contenir l'inverse de l'instruction originale. Comment l'écriture du modèle sur la console modifie-t-elle la fonctionnalité du code? Ce comportement est-il documenté?L'impression InfModel plus tôt modifie la représentation imprimée plus tard?

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

Répondre

0

Il est probable que model.toString() ait des effets de bord. Je n'ai pas regardé la source de JENA, donc je ne peux pas être sûr, cependant.

+0

Merci pour la réponse - Je pense que ce n'est pas seulement "probable" mais aussi complètement évident que toString() doit avoir des effets secondaires. Ce qui est certainement inattendu, mais peut-être que mon expérience avec Jena est trop peu pour savoir ce qui se passe. En tout cas, je n'ai trouvé aucune documentation de ce comportement. –

1

jeté un coup d'œil à la source pertinente et il semble que vous avez deux options:

  • Si vous souhaitez apporter des modifications à la base modèle et assurez-vous qu'ils se propagent à la infModel, alors vous devez appeler infModel.rebind() après avoir fait les modifications et avant de "demander" le infModel quoi que ce soit.

  • Vous pouvez utiliser le infModel directement (au lieu de modèle) pour créer et ajouter des éléments de la déclaration et la déclaration elle-même.

Je sais que cela ne répond pas directement à votre question, mais il peut résoudre votre problème (qui, d'ailleurs, semble être causé par la réification déclenchée par la toString() méthode dans ModelCom - le parent classe de InfModel).

0

Cela fait maintenant quelques années que Jena fait partie de la série 2.10.x. Lorsque la ligne indiquée est commentée, la sortie de votre programme est:

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

et la représentation de chaîne de la InfModel contient deux chambres triples. Lorsque la ligne est uncommented, la sortie est:

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

et la seconde chaîne de caractères représentant le InfModel ne dispose que d'une triple, de sorte que la différence est encore observée. (I inclus la sortie ici, parce que dans la question, il ne sait pas ce que différence était observée.)

La réponse courte est que cela arrive parce que vous être sournoise et modifier model sans dire que vous infModel changé le sous-jacent model.Pour résoudre ce problème, vous devez ajouter un appel à infModel.rebind(); après la mise à jour model. Autrement dit, vous auriez maintenant:

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

Lorsque vous faites cela, vous obtiendrez le même résultat dans les deux cas. Avec la ligne a commenté:

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

Avec la ligne décommentée:

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

Je suppose ici que l'écriture de la représentation de chaîne de la InfModel ne provoque aucune inférence à réaliser à moins qu'aucune inférence n'a été effectué encore, puis imprime le modèle sous-jacent, puis tous les triplets supplémentaires qui sont déduits. En conséquence:

  • Dans le premier cas (lorsque vous imprimez infModel juste une fois), il n'a pas encore fait une inférence, il consulte model et fait l'inférence appropriée et obtient les triplets supplémentaires. Puis il imprime les triplets de model puis les triplets déduits.
  • Dans le second cas (lorsque vous imprimez infModel deux fois), la première fois que vous imprimez infModel, il consulte model et fait une inférence, mais model est vide, donc il n'y a pas triplets supplémentaires, puis il imprime triplets de model et les triplets supplémentaires déduits (il n'y en a pas). Ensuite, la deuxième fois infModel est imprimée, l'inférence a déjà été effectuée, donc elle imprime les triplets de model (mais il y en a un de plus) et tous les triplets déduits (il n'y en a pas, car aucune inférence n'a été faite).

L'appel à rebind() après avoir ajouté triples à model signifie que, dans le second cas, les triples inférées supplémentaires sont disponibles au moment de l'impression.

Questions connexes