简体   繁体   中英

Create a new object using the inference rules

I have a semantic network. Is it possible to use a jena framework to create a new object in the semantic web based on some rule. For example there is an object has a certain property, then you need to create a new object and make a connection between them. Is it possible?

Yes, this is possible in Jena's rule system. Typically, we create such nodes using the makeSkolem Reasoner Builtin Primitive :

[example:
  (?a urn:ex:owns ?b) 
  makeSkolem(?ownership,?a,?b)
  ->
  (?a urn:ex:hasOwnership ?ownership)
  (?ownership urn:ex:of ?b)
]

This will create a new blank node in the graph that will be used to reify the <urn:ex:owns> triple. Eg, when given a graph containing the triple <urn:ex:a> <urn:ex:owns> <urn:ex:b> as input, the preceding rule will generate the following graph structure:

<urn:ex:a> <urn:ex:hasOwnership> [
  <urn:ex:of> <urn:ex:b>
].

You can also construct URIs in your rule if you have some scheme for generating them.

Java Example

Assuming that so.rules exists on your classpath and contains the rule from above, the following java code will demonstrate custom rules for this task.

// Obtains a list of rules to pass to a rule-based reasoner
// These rules are read from a file.
// This is the most common case.
final List<Rule> rules;
try (final InputStream src = Resources.getResource("so.rules").openStream()) {
  rules = Rule
      .parseRules(Rule.rulesParserFromReader(new BufferedReader(new InputStreamReader(src))));
}

// Create a rule-based reasoner.
// There are multiple types of reasoners available.
// You may prefer some over others (e.g., when performing OWL inference in tandem with custom rules)
final GenericRuleReasoner reasoner =
    (GenericRuleReasoner) GenericRuleReasonerFactory.theInstance().create(null);
reasoner.setRules(rules);

// Create a RDF Model to store data in.
// Create an inference model to interact with.
// The inference model will store any added data in the base model.
// The inference model will store inferred triples internally.
final Model baseModel = ModelFactory.createDefaultModel();
final InfModel model = ModelFactory.createInfModel(reasoner, baseModel);
model.prepare();

// Stimulate the rule by introducing the desired triples to the graph
// :a :owns :b
final Property owns = model.createProperty("urn:ex:", "owns");
final Property hasOwnership = model.createProperty("urn:ex:","hasOwnership");
final Property of = model.createProperty("urn:ex:","of");

final Resource a = model.createResource("urn:ex:a");
final Resource b = model.createResource("urn:ex:b");
model.add(a,owns,b);

// Verify that the rule has fired. That is, that we have created some node
// and that the node relates our other two resources
// -> :a :hasOwnership [ :of :b ]
assertTrue(a.hasProperty(hasOwnership));
final Resource createdObject = a.getPropertyResourceValue(hasOwnership);
assertTrue(createdObject.hasProperty(of,b));

If you needs are reasonably simple you can use SPARQL CONSTRUCT queries, ie

CONSTRUCT { ?p :hasGrandfather ?g . }

WHERE {
   ?p      :hasParent ?parent .
   ?parent :hasParent ?g .
   ?g      :gender    :male .
}

will cause triples to be generated for stating grandfather relations.

If your needs are more sophisticated, you can achieve this with SHACL for which an implementation on top of Jena exists. I will give a brief example. Assume you have the following RDF data:

@prefix ex: <http://example.com/ns#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

ex:InvalidRectangle
    a ex:Rectangle .

ex:NonSquareRectangle
    a ex:Rectangle ;
    ex:height 2 ;
    ex:width 3 .

ex:SquareRectangle
    a ex:Rectangle ;
    ex:height 4 ;
    ex:width 4 . 

for which you define the following shape file:

@prefix ex: <http://example.com/ns#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix dash: <http://datashapes.org/dash#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ex:Rectangle
    a rdfs:Class, sh:NodeShape ;
    rdfs:label "Rectangle" ;
    sh:property [
        sh:path ex:height ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minCount 1 ;
        sh:name "height" ;
    ] ;
    sh:property [
        sh:path ex:width ;
        sh:datatype xsd:integer ;
        sh:maxCount 1 ;
        sh:minCount 1 ;
        sh:name "width" ;
    ] ;
    sh:rule [
        a sh:TripleRule ;
        sh:subject sh:this ;
        sh:predicate rdf:type ;
        sh:object ex:Square ;
        sh:condition ex:Rectangle ;
        sh:condition [
            sh:property [
                sh:path ex:width ;
                sh:equals ex:height ;
            ] ;
        ] ;
    ] .

It will generate the following RDF data:

@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .

<http://example.com/ns#SquareRectangle>
        a       <http://example.com/ns#Square> .

which you can add to your RDF store.

This example with code can be found here , as well as a more advanced example .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM