How to make Custom Rule set in Graphdb - rule-engine

I am trying to make customs rules in Graphdb. I have a Person ontology which has classes "Parent" and "Child", and object property "hasChild" and "hasGrandChild".
There are three nodes with relationship like this:
:Ali :hasChild :Aslam
:Aslam :hasChild :Ahmed
Now I want to infer that ":Ali :hasGrandChild :Ahmed" in Graphdb. Builtin ruleset like owl horst optimized does not work.
I tried using .pie file for making custom rules but new rules are not working

GraphDB gives you the flexibility to develop your own rules if you want to express semantics not part of the OWL or RDFS standards. In this example, you try to define that the property hasGranChild is a chain of two hasChild properties. This is possible with OWL property chain axiom.
My suggestion is to use the standard OWL semantics part of OWL 2 RL and OWL 2 QL rulesets in GraphDB. Here is an example:
#prefix : <http://www.example.org/> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
:hasParent a owl:ObjectProperty .
:hasGrandChild owl:propertyChainAxiom
( :hasChild :hasChild ) .
:Ahmed :hasChild :Ali .
:Ali :hasParent :Aslam .
Please do not forget to change the default ruleset to OWL 2 RL or OWL 2 QL during the repository creation.

I created a ruleset file called “CustomRule.pie”. It has three main parts “Prefices”, “Axioms”, and “Rules”.
In Prefices, I inserted our ontology Prefix like:
Person :http://www.semanticweb.org/hamza/ontologies/2017/6/Person.owl#
Then in Axioms, we have to write all the triples Subject, Predicate, Object that we have inserted in our ontology. Like:
<'Person:Ahmed'> <'Person:hasChild'> <'Person:Ali'>
<'Person:Ali'> <'Person:hasChild'> <'Person:Aslam'>
//Ingore commas
Finally, in Rules section, we can write entailment rules. It checks all the axioms available in the Axioms section to implement rules. Like
Id: custom
a <'Person:hasChild'> b
b <'Person:hasChild'> c
------------------------------------
a <'Person:hasGrandChild'> c

Related

How to generate code from custom scoping through instances?

I'm trying to write a code generator using xtext. There are instances of types declared in the corresponding DSL, attributes can be referenced through those instances by custom scoping (see code for example). The linking is performed directly from referencing element to attribute, so that there is no information about the surrounding instance - but for code generation, I exactly need the qualified name that is added in the DSL file. Is there any other possibility so that I can figure out through which instance the actual feature is referenced?
My first idea was to recall the ScopeProvider at code generation, which works but does not react on two instances of same type because the first matching Attribute is chosen - so if there are multiple instances, the generator cannot distinguish which one is meant.
Second idea was to include information from the corresponding DSL file, but I don't have any idea how to get this work. I already searched a lot if it is possible to get the corresponding DSL-file from the current model, but could not find any helpful answer.
Third idea was to include the instance as a hidden field in the referencing element - but I could not find any solution for this approach too.
Small extract of Grammar (simplified):
Screen:
(features += ScreenFeature)*
;
ScreenFeature:
name=ID ':' type=[ClientEntity]
;
ClientEntity:
(features += Feature)*
;
Feature:
name=ID ':' type=DefaultValue
;
DefaultValue:
'String'|'int'|'double'|'boolean'
;
ChangeViewParam:
param=[ScreenFeature|QualifiedName] ':' value=[ScreenFeature|QualifiedName]
;
DSL-Example:
ClientEntity Car {
id : int
name : String
}
Screen Details {
car : Car
car2 : Car
[...]
car2.id : car.id
}
Generation output of first approach (line: car2.id : car.id) :
car.id : car.id
Expected:
car2.id : car.id
I hope you can understand my problem and have an idea how to solve it. Thanks for your help!
You can use
org.eclipse.xtext.nodemodel.util.NodeModelUtils.findNodesForFeature(EObject, EStructuralFeature) to obtain the nodes for YourDslPackage.Literals.CHANGE_VIEW_PARAM__PARAM (should be only one) and ask that one for its text.
Alternatively you could split your param=[ScreenFeature|QualifiedName] into two references

RDF4J not filtering TreeModel in expected way

I have a TTL with something like
ex:isDataProperty rdf:type owl:DatatypeProperty .
ex:Article a owl:Class ;
owl:hasKey ( ex:isDataProperty ) .
And when I load the model with RDF4J (as a TreeModel) then try to filter to extract the properties annotated with haskey fails (just returns empty list result)
Some samples that return data:
val dataProperties = model.filter(null, RDF.TYPE, OWL.DATATYPEPROPERTY).subjects().asScala
val classes = model.filter(null, RDF.TYPE, OWL.CLASS).subjects().asScala
The sample I want, that doesn't return data:
val propertiesWithKeys = model.filter(null, RDF.PROPERTY, OWL.HASKEY).subjects().asScala
I have tried a few variations of the previous one using RDF.TYPE or RDF.Value. (instead of RDF.PROPERTY)
The thing you're after is any subject that has a owl:hasKey property, regardless of value. So both the subject and the object are wildcards, you just want to filter by property name. The way to do that is like this:
model.filter(null, OWL.HASKEY, null)
Now, furthermore you say that you want to know the properties that have been used as annotation using this owl:hasKey property. In your example, that would be ex:isDataProperty. Note that in your model, this is not the subject of the owl:hasKey relation - it's in the object values:
model.filter(null, OWL.HASKEY, null).objects()
To further complicate matters, the object values in your example are not simply single values. Instead, each class is annotated using a list of properties, so the object value is a list object (a.k.a. an RDF Collection). To process this list, there are some utility methods provided by the Models and RDFCollections classes.
For each of the objects you can do this to get the actual list of values:
RDFCollections.asValues(model, objectNode, new ArrayList<Value>())
(where objectNode is one of the values that .objects() returned)
Edit since objects() returns objects of type Value and RDFCollections expects a Resource, you'll either have to do a cast, or if you want to do all of this in a fluent way, you can use Models.objectResources instead. The whole thing then becomes:
Models.objectResources(model.filter(null, OWL.HASKEY, null))
.asScala.map(o => RDFCollections.asValues(model, o, new ArrayList[Value]()));
(I may have the Scala-specific bits of this wrong, but you get the gist hopefully)
For more information on how to work with the rdf4j Model API and with RDF Collections, see the rdf4j documentation.

How to isolate a list of URIs in a RDF file using CONSTRUCT or DESCRIBE in SPARQL?

I'm trying to get only a list of URIs in RDF instead of a list of triples:
PREFIX gr: <http://purl.org/goodrelations/v1#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
DESCRIBE ?product
WHERE
{
?product rdfs:subClassOf gr:ProductOrService .
}
Using SELECT, instead of DESCRIBE I receive only the subject (which I want), but not as an RDF but like a SPARQL Result with binds, vars, etc.
Using CONSTRUCT, I can't specify only the ?product, as above, so the closest I can get is:
PREFIX gr: <http://purl.org/goodrelations/v1#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
CONSTRUCT
WHERE
{
?product rdfs:subClassOf gr:ProductOrService .
}
Which returns an RDF with triples of different products, but the same properties and objects.
It looks like you should read over the SPARQL specification, which tells you that this is exactly as expected. To get the single column you wish, you must use SELECT.
SPARQL has four query forms. These query forms use the solutions from pattern matching to form result sets or RDF graphs. The query forms are:
SELECT
Returns all, or a subset of, the variables bound in a query pattern match.
CONSTRUCT
Returns an RDF graph constructed by substituting variables in a set of triple templates.
ASK
Returns a boolean indicating whether a query pattern matches or not.
DESCRIBE
Returns an RDF graph that describes the resources found.
I found a solution. I've used SELECT, but instead of binds and vars, as output received a "Comma-Separated Values (with fields in N-Triples syntax)" CSV file:
<http://www.productontology.org/id/Real_estate>
<http://www.productontology.org/id/Automobile>
<http://www.productontology.org/id/Auction>
<http://www.productontology.org/id/Video_game>
<http://www.productontology.org/id/Campsite>
<http://www.productontology.org/id/Car>
<http://www.productontology.org/id/Audiobook>
<http://www.productontology.org/id/Browser_game>
...
Representing the result of a SPARQL SELECT query as an RDF List is a tooling issue - it is not something that can be solved in SPARQL in general.
Some SPARQL tools may have ways to support rendering the query result as an RDF list. But it's not something you can fix by just formulating your query differently, you'll need to use a tool to (programmatically) format the result.
In Java, using Eclipse RDF4J, you can do it as follows (untested so you may need to tweak it to work properly, but it should give you a general idea):
String query = "SELECT ?product WHERE { ?product rdfs:subClassOf gr:ProductOrService . }";
// do the query on repo and convert to a Java list of URI objects
List<URI> results = Repositories.tupleQuery(
repo,
query,
r -> QueryResults.stream(r).map(bs -> (URI)bs.getValue("product")).collect(Collectors.toList()
);
// create a resource (bnode or URI) for the start of the rdf:List
Resource head = SimpleValueFactory.getInstance().createBNode();
// convert the Java list of results to an rdf:list and add it
// to a newly-created RDF Model
Model m = RDFCollections.asRDF(results, head, new LinkedHashModel());
Once you have your result as an RDF model you can use any of the existing RDF4J APIs to write it to file or to store it in a triplestore.
Now, I am not claiming that any of this is a good idea - I have never seen a use case for something like this. But this is how I would do it if it were necessary.

Define class hierarchy in Notation 3

I am trying to develop a simple Notation3 ontology file.
so far my code in the notation3 file is
#prefix my: <http://www.codeproject.com/KB/recipes/n3_notation#>.
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
my:batterycs a my:spec;
my:preferedby my:BusinessPerson, my:LoveBird, my:MusicLover, my:Travelar;
my:name "batteryCS".
rdfs:Person a rdfs:Class.
I am using dotNetRdf library to read and query the ontology file. the above code in n3 file works fine. But when I Insert
rdfs:Woman a rdfs:Class; rdfs:subClassOf :Person .
at the end of the ontology file it occurs the error Unable to resolve the QName ':Person' seems like it cant even load the ontology to the parser.
I studied the n3 syntax from http://www.w3.org/2000/10/swap/Primer.html
can somebody help me with this where I have made the mistake
thanks in advance
Your data is invalid, you need to define the empty prefix in order to be able to refer to it in a QName such as :Person
A QName (Qualified Name) is a syntactic shortcut which allows you to shorten URIs written in the form prefix:name where prefix must refer to a defined namespace prefix defined via a previous #prefix statement. The parser then simply looks up the prefix and concatenates it with the name part, so for example rdfs:Class is expanded to http://www.w3.org/2000/01/rdf-schema#Person in your example data.
If a prefix is not defined then a RDF parser is expected to throw an error.
So you need to fix your data, there are a couple of ways to do this depending on what your intent was.
You meant to put :Person in your own my: namespace
Simply replace :Person with my:Person
Note that you have also referred to rdfs:Person so your data looks somewhat inconsistent
You meant to defined an empty namespace
Simply add the following #prefix definition:
#prefix : <http://example.org/namespace#> .
Where the URI is the desired namespace URI
Aside
What version of dotNetRDF are you using? And is the error message you quote the complete error message?
More recent versions of dotNetRDF are supposed to give more informative error messages that should have told you that you were likely missing a prefix declaration

RDF document metadata

I have a software that generates an RDF representation of certain dataset. I want to add to the generated data also some metadata describing not specific data contained in the data set but the document itself - i.e., when the document was created, by which software, which version, etc. The schema.org properties provide the necessary relationships, but I can not figure out the proper place to attach it. Is there some standard way of saying "this is the metadata about the document itself" in RDF? I use Turtle serialization for RDF but generic answer working with any serialization would be preferable.
There is not a standard place to do this. A RDF graph is just a collection of triples; it's not identified by an IRI or anything like that. (However, in SPARQL datasets, you could post some metadata about a named graph by using the name of the graph as the subject in a triple. That would just be a convention, though. It's not "official" in any sense.)
In the RDF serializations of OWL ontologies, there can be an ontology element (i.e., a resource with the type owl:Ontology), and that can be used to associate some metadata with the ontology. You'd probably want to adopt an approach like that. That is, you'd establish a convention with something like
#prefix ex: <...>
[] a ex:DatasetRepresentation ;
ex:created "..." ;
ex:representationOf <...> .
#... rest of generated content ...
I am not that familiar with Schema.org, but both DCat and Doublin Core provide means to do so.
In Doublin Core there is the identifier Data property. An example:
PREFIX : <http://my.domain/meta-data#>
PREFIX dcterms: <http://purl.org/dc/terms/>
:1 a dcterms:BibliographicResource ;
dcterms:identifier <http://my.domain/my-document> .
A similar record but now using DCat and the landingPage data property:
PREFIX : <http://my.domain/meta-data#>
PREFIX dcat: <http://www.w3.org/ns/dcat#>
:1 a dcat:Resource ;
dcat:landingPage <http://my.domain/my-document> .