Reasoning with Pellet on SWRL rules in Jena Framework - jena

I am trying to use Jena framework to edit an existing ontology built with Protoge 4.2. i.e. to change property values or add individuals or classes and then do reasoning. Assume in the ontology we have a rule such that: hasAge(?p,?age)^swrlb:greaterThan(?age,18)->Adult(?p). I would like to be able to change hasAge property on Jena side and see if someone is an Adult or not. Can you please provide me some sample code on this? Any help is appreciated.

Assuming that :
you know how to populate your model by reading in the ontology that you built
You have put Pellet on the classpath
You replace the IRI's below with those from your domain
You have assertions enabled
The following code snippet will add an age to an individual x-test://individual and assert that the property that would be introduced by SWIRL is satisfied.
// create an empty ontology model using Pellet spec
final OntModel model = ModelFactory.createOntologyModel( PelletReasonerFactory.THE_SPEC );
// read the file
model.read( ont );
// Grab a resource and and property, and then set the property on that individual
final Resource Adult = ResourceFactory.createResource("x-domain://Adult");
final Property hasAge = ResourceFactory.createProperty("x-domain://hasAge");
final Resource res = model.createResource("x-test://individual");
res.addLiteral(hasAge, 19);
// Test that the swirl rule has executed
assert( res.hasProperty(RDF.type, Adult) );

Related

Why does my custom spaCy entity type get detected?

I am writing a spaCy program for which I want to define a custom named entity tag. Following the example here, I add a label called MY_NEW_LABEL to the pipeline.
import spacy
nlp = spacy.load("en_core_web_lg")
ner = nlp.get_pipe("ner")
new_label = "MY_NEW_LABEL"
ner.add_label(new_label)
documents_path = "my_document.txt"
document = nlp(open(documents_path).read())
print([e for e in document.ents if e.label_ == new_label])
When I run the above program it prints out a list of entities labeled with MY_NEW_LABEL. I don't see how this is possible because I never do anything with the label.
Clearly I'm misunderstanding how to work with custom entity tags, but I can't figure out why this would be happening from the documentation. Can anyone tell me why my program doesn't print out an empty list?
This is unexpected behavior. I opened it as spaCy issue 1697: Custom Entity Labels Are Erroneously Detected.

Edit an OWL Individual using OWL API

I have an ontology created in protege 4. I need to add a data property to an owl individual of my ontology using OWL API 4. i am new to java / owl api so to my understanding. i used following code:-
OWLNamedIndividual myowlIndl = df.getOWLNamedIndividual(":test", pm);
OWLDataProperty indlName = df.getOWLDataProperty(":strVal", pm);
OWLDataPropertyAssertionAxiom dataPropertyAssertion = df.getOWLDataPropertyAssertionAxiom(indlName, myowlIndl,"hello world");
AddAxiom addAxiom1 = new AddAxiom(myowlOntology, dataPropertyAssertion);
myontologyManager.applyChange(addAxiom1);
but this code do not "Update" already existing owl individual "test" but create a new one.
How to rectify this?
Use the full IRI instead of a shortened version, it is hard to tell from this code whether the namespace is the correct one (":test" is ambiguous, since we cannot see how the prefix manager resolves it, and we cannot see the ontology).
Also, make sure to save the ontology after the call to applyChange().

Add custom data to breeze metadata on server

In a app I'm developing I create some UI widgets that are generated based on breeze metadata and attributes on my classes and properties. So on the server I read the attributes, and add them on breeze's generated metadata. On the client, after I load the metadata I add those attributes on the type.
An example of this
(on the client, after the enriched metadata loads):
function finishMetadata(md) {
for (var i = 0; i < md.schema.entityType.length; i++) {
var et = md.schema.entityType[i];
var etype = manager.metadataStore.getEntityType(et.name);
//isExportable is a class attribute
etype.isExportable = et.isExportable;
for (var j = 0; j < et.property.length; j++) {
var p = et.property[j];
var prop = etype.getProperty(p.name);
//displayName is a property attribute
prop.displayName = p.displayName ? p.displayName : p.name;
}
}
}
with this, when I call manager.metadataStore.getEntityType(entityName), I get all the entityType data, including the properties and all the attributes I added on the server.
This worked fine until today. I have added inheritance (TPT) on some classes (Customer:Person) and since the generated metadata from the Customer entity does not have the Person properties, I cannot add them to the metadataStore type. When I call metadataStore.getEntityType for Person, I get all attributes, but when I call it for Customer I do not get my custom attributes (and this is because on the code above Customer does not list the parent Person properties so I do not have the chance to plug in my custom attributes.
Anyway, this feels hacky and messy, even to explain it. So here we are, breeze its in version 1.4.7 and I wonder if there is an easier way of adding custom data to the metadata that would not break with TPT?
PS.: I know that I can hand-craft the metadata but I would like to stick with the default as much as possible to avoid problems with future changes. So, basically all metadata changes should be minimal and automatic, based on the classes.
Well, I ended up goind further down on the way I'm doing things. Instead of just use manager.metadataStore.getEntityType to get the type data (which does not bring my custom metadata), I look if my entityType has a baseType and if it does, I load that base type data and merge it with the child class. In my case, basically I get the dataProperties of the Person and use them instead of the dataProperties of the Customer. It works but I still looking for a cleaner and simpler way of doing something like this.

How to build a custom Lucene index for Neo4j graph?

I am using Gremlin and Neo4j to manipulate the ENRON dataset from infochimps. This dataset has two types of vertexes, Message and Email Addresss and two types of edges, SENT and RECEVIED_BY. I would like to create a custom index on this dataset that creates a Lucene document for each vertex of type: 'Message' and incorporates information from associated vertexes (e.g., v.in(), v.out()) as additional fields in the Lucene document.
I am thinking of code along the lines of
g = new Neo4jGraph('enron');
PerFieldAnalyzerWrapper analyzer =
new PerFieldAnalyzerWrapper(new StandardAnalyzer());
analyzer.addAnalyzer("sender", new KeywordAnalyzer());
analyzer.addAnalyzer("recipient", new KeywordAnalyzer());
IndexWriter idx = new IndexWriter (dir,analyzer,IndexWriter.MaxFieldLength.UNLIMITED);
g.V.filter{it.type == 'Message'}.each { v ->
Document doc = new Document();
doc.add(new Field("subject", v.subject));
doc.add(new Field("body", v.body));
doc.add(new Field("sender", v.in().address);
v.out().each { recipient ->
doc.add(new Field("recipient", recipient.address));
}
idx.addDocument(doc);
}
idx.close();
My questions are:
Is there a better way to enumerate vertexes for indexing?
Can I use auto-indexing for this, and if so, how to I specify what should be indexed?
Can I specify my own Analyzer, or am I stuck with the default? What is the default?
If I must create my own index, should I be using gremlin for this, or am I better off with a Java program?
I will be talking about direct Neo4j access here since I'm not well travelled in Gremlin.
So you'd like to build a Lucene index "outside of" the graph itself? Otherwise you can use the built in graphDb.index().forNodes( "myIndex", configForMyIndex ) to get (created on demand) a Lucene index associated with neo4j. You can then add multiple fields to each document by calling index.add( node, key, value ), where each node will be represented by one document in that Lucene index.
1) In Gremiln... I don't know
2) See http://docs.neo4j.org/chunked/milestone/auto-indexing.html
3) See http://docs.neo4j.org/chunked/milestone/indexing-create-advanced.html
4) Do you need to create it outside of the db entirely? If so, why?
I just finished an import with a Java process and it's really easy, in my opinion better inclusive through Gremlin.
Anyway, if the process is failing is because of you CAN'T create a new object of StandardAnalyzer. All the constructors of that class require parameters, so you should create a wrapper class or create it with the right version of Lucene like paramater in the constructor.
Neo4J, until today, accepts only until the lucene version 36.

Jena throwing ConversionException when trying to cast to OntClass

I have a particular Class URI for which I am trying to get an OntClass. The model is a regular model.
I wrote some code to find out whether the right statements were in the model, and it seems that they are so I can't understand why it won't let me view this as an OntClass. (tblURI is a String passed as a method parameter)
Resource tblR = m.createResource(tblURI);
List<Statement> prp = tblR.listProperties().toList();
for(Statement s : prp)
System.out.println(s);
System.out.println(tblR.canAs(OntClass.class));
OntClass tbl = tblR.as(OntClass.class);
This is the output:
[kps:datasource/EnsembleMS#translation_stable_id, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, http://www.w3.org/2002/07/owl#Class]
[kps:datasource/EnsembleMS#translation_stable_id, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, http://www.w3.org/2000/01/rdf-schema#Class]
[kps:datasource/EnsembleMS#translation_stable_id, http://www.w3.org/2000/01/rdf-schema#isDefinedBy, kps:datasource/EnsembleMS]
[kps:datasource/EnsembleMS#translation_stable_id, http://www.w3.org/2000/01/rdf-schema#label, "translation_stable_id"]
false
com.hp.hpl.jena.ontology.ConversionException: Cannot convert node kps:datasource/EnsembleMS#translation_stable_id to OntClass: it does not have rdf:type owl:Class or equivalent
at com.hp.hpl.jena.ontology.impl.OntClassImpl$1.wrap(OntClassImpl.java:81)
at com.hp.hpl.jena.enhanced.EnhNode.convertTo(EnhNode.java:155)
at com.hp.hpl.jena.enhanced.EnhNode.convertTo(EnhNode.java:34)
at com.hp.hpl.jena.enhanced.Polymorphic.asInternal(Polymorphic.java:66)
at com.hp.hpl.jena.enhanced.EnhNode.as(EnhNode.java:110)
at com.KPS.myApp.exampleMethod(myApp.java:123)
Why is it throwing an exception and how can I get an OntClass for the resource with uri tblURI?
Thanks for any pointers
You don't say what kind of model m is. In particular, if m was created with the RDFS language profile, the OntModel will be looking for an rdf:type of rdfs:Class, not owl:Class. If that's not the issue, then a complete minimal (i.e. runnable) example would help.
By the way, there's another problem I can see: resource URI's in the model should be in absolute form, not abbreviated form. The fact that you've got q-name URI's in your model, like kps:datasource/EnsembleMS#translation_stable_id, suggest that something is going wrong with your prefix handling. That won't by itself cause the problem you've reported, but it's a red flag to investigate.
Update
Responding to questions:
yes, you need to be using an OntModel, otherwise it's not possible for the OntClass to know which langauge profile to use. Either create the model as OntModel in the first place:
OntModel m = modelFactory.createOntologyModel( OntModelSpec.OWL_MEM );
or wrap your plain model as an OntModel:
OntModel om = modelFactory.createOntologyModel( OntModelSpec.OWM_MEM, m );
Of course, you many use any of the model specifications, as you please, OWL_MEM is just one option.
createResource will not expand prefixes for you. So, you should expand them yourself before creating the resource:
m.createResource( m.expandPrefix( "foo:bar" ) );
Of course, this requires the prefix "foo" to be registered as a prefix. This happens automatically if you read an RDF document that defines the prefix in its syntax, but otherwise can be done manually with setNsPrefix.

Resources