This is a simplified extract from my ontology:
<owl:Class rdf:ID="Role" />
<owl:Class rdf:ID="Location" />
<owl:Class rdf:ID="SalaryRange">
<rdfs:subClassOf rdf:resource="#HasLocation" />
</owl:Class>
<owl:Class rdf:ID="HasLocation" />
<owl:ObjectProperty rdf:ID="location">
<rdfs:domain rdf:resource="#HasLocation" />
<rdfs:range rdf:resource="#Location" />
</owl:ObjectProperty>
<owl:DataProperty rdf:ID="salaryRangeOfRole">
<rdfs:domain rdf:resource="#Role" />
<rdfs:range rdf:resource="#SalaryRange" />
</owl:DataProperty>
How can I ensure now that the Locations in the SalaryRanges are unique per Role?
I have read about FunctionalPropertys, but do not see how to use this in this case.
The challenge you have here is that you basically want a unique constraint on Role and Location for SalaryRange. Funtional properties really is defined for a single property - except if you do model some functional property through class expressions.
A simple way to achieve this (if you are using OWL) is through key constraints. I battle a bit to understand your example. I therefore simplified your example further to assuming you have a SalaryRange for which the Role and Location need to be unique. I think if you understand the general idea you will be able to modified it to fit your example exactly.
We have the classes Location and Role as you defined it.
<owl:Class rdf:about="Location"/>
<owl:Class rdf:about="Role"/>
Then I defined object properties role and location follows:
<owl:ObjectProperty rdf:about="location">
<rdfs:domain rdf:resource="SalaryRange"/>
<rdfs:range rdf:resource="Location"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:about="role">
<rdfs:domain rdf:resource="SalaryRange"/>
<rdfs:range rdf:resource="Role"/>
</owl:ObjectProperty>
Then to ensure that SalaryRange will have unique roles and locations, you can enforce it as follows:
<owl:Class rdf:about="SalaryRange">
<owl:hasKey rdf:parseType="Collection">
<rdf:Description rdf:about="location"/>
<rdf:Description rdf:about="role"/>
</owl:hasKey>
</owl:Class>
You can test this with the following individuals:
<owl:NamedIndividual rdf:about="location1">
<owl:sameAs rdf:resource="location2"/>
</owl:NamedIndividual>
<owl:NamedIndividual rdf:about="location2"/>
<owl:NamedIndividual rdf:about="role1">
<owl:sameAs rdf:resource="role2"/>
</owl:NamedIndividual>
<owl:NamedIndividual rdf:about="role2"/>
<owl:NamedIndividual rdf:about="salaryRange1">
<location rdf:resource="location1"/>
<role rdf:resource="role1"/>
</owl:NamedIndividual>
<owl:NamedIndividual rdf:about="salaryRange2">
<location rdf:resource="location2"/>
<role rdf:resource="role2"/>
</owl:NamedIndividual>
With these individuals a reasoner like Hermit will infer that salaryRange1 and salaryRange2 are the same individual. However, if you state that salaryRange1 and salaryRange2 are different individuals, you will get an inconsistency.
<rdf:Description>
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AllDifferent"/>
<owl:distinctMembers rdf:parseType="Collection">
<rdf:Description rdf:about="salaryRange1"/>
<rdf:Description rdf:about="salaryRange2"/>
</owl:distinctMembers>
</rdf:Description>
To resolve the inconsistency you can state that either role1 and role2 are different individuals OR location1 and location2 are different individuals.
Related
I am using the OWL-API 5 to load all the object property axioms in my ontology as follows:
File ontology = new File("examples/ontology.owl");
File individual = new File("examples/individuals.owl");
OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
IRI documentIRI = IRI.create(ontology);
IRI ontologyIRI = IRI.create("http://www.semanticweb.org/2020/0/test");
SimpleIRIMapper mapper = new SimpleIRIMapper(ontologyIRI, documentIRI);
manager.getIRIMappers().add(mapper);
OWLOntology kb = manager.loadOntologyFromOntologyDocument(individual);
Stream<OWLObjectPropertyAssertionAxiom> objectPropertyAxioms = kb.axioms(AxiomType.OBJECT_PROPERTY_ASSERTION);
objectPropertyAxioms.forEach(axiom -> {
System.out.println("Found object property axiom " + axiom);
OWLIndividual object = axiom.getObject();
OWLIndividual subject = axiom.getSubject();
OWLObjectPropertyExpression property = axiom.getProperty();
});
Returns:
Found object property axiom ObjectPropertyAssertion(<http://www.semanticweb.org/2020/0/test#Q> <http://www.semanticweb.org/2020/0/test#x> <http://www.semanticweb.org/2020/0/test#y>)
Now, I'd like to determine if the property is functional. This is what I tried so far:
if (EntitySearcher.isFunctional(property, kb)) {
LOGGER.debug("Property " + property + " is declared as functional");
} else {
LOGGER.debug("Property " + property + " is NOT declared as functional");
}
Returns:
Property <http://www.semanticweb.org/2020/0/test#Q> is NOT declared as functional
I think that EntitySearcher.isFunctional(p,o) is looking for functional object property axioms that make the specified object property functional, which doesn't seems to exist in my ontology (i.e., ontology.axioms(AxiomType.FUNCTIONAL_OBJECT_PROPERTY) returns nothing).
This is what I have in my ontology:
<?xml version="1.0"?>
<rdf:RDF xmlns="http://www.semanticweb.org/2020/0/test#" xml:base="http://www.semanticweb.org/2020/0/test" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:Ontology rdf:about="http://www.semanticweb.org/2020/0/test"/>
<owl:ObjectProperty rdf:about="http://www.semanticweb.org/2020/0/test#Q">
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/>
</owl:ObjectProperty>
</rdf:RDF>
And individuals:
<?xml version="1.0"?>
<rdf:RDF xmlns="http://www.semanticweb.org/2020/0/test#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:Ontology rdf:about="">
<owl:imports rdf:resource="http://www.semanticweb.org/2020/0/test"/>
</owl:Ontology>
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/2020/0/test#x">
<Q rdf:resource="http://www.semanticweb.org/2020/0/test#y"/>
</owl:NamedIndividual>
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/2020/0/test#y"/>
</rdf:RDF>
(Both files were created using Prótegé 5.5.0). Any suggestions? Thank you.
To answer the implicit question about EntitySearcher::isFunctional, yes, it checks if there are functional property axioms for the property received in input.
I believe your ontology has enough information for that.
To provide a complete example:
<?xml version="1.0"?>
<rdf:RDF xmlns="http://www.semanticweb.org/2020/0/test#" xml:base="http://www.semanticweb.org/2020/0/test" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:test="http://www.semanticweb.org/owlapi/test#">
<owl:Ontology rdf:about="http://www.semanticweb.org/2020/0/test"/>
<owl:ObjectProperty rdf:about="http://www.semanticweb.org/owlapi/test#Q">
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#FunctionalProperty"/>
</owl:ObjectProperty>
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/owlapi/test#x">
<test:Q rdf:resource="http://www.semanticweb.org/owlapi/test#y"/>
</owl:NamedIndividual>
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/owlapi/test#y"/>
</rdf:RDF>
With this ontology, EntitySearcher returns true when checking for functional properties.
Edit: in your updated question, you're using kb.axioms(AxiomType), you need to tell it to include imports.
In the food ontology http://www.w3.org/TR/2004/REC-owl-guide-20040210/food#, I am seeing this way of representing classes and individuals:
<owl:Class rdf:ID="RedMeat">
<rdfs:subClassOf rdf:resource="#Meat"/></owl:Class>
<SweetDessert rdf:ID="Cake"/>
<SweetFruit rdf:ID="Bananas"/>
<SweetFruit rdf:ID="MixedFruit"/>
For the individuals "Cake", "Bananas" and "MixedFruit", why doesn't it use:
<OWL:NamedIndividual>
</OWL:NamedIndividual>
Is that because the food ontology is represented in old syntax?
I am a bit confused about the subclass handling in Protégé as compared to when using the OWL API directly.
I have built a simple ontology where I logically define what a "Man" or a "Woman" is, namely male or female humans.
The classes are
Human
Woman
Man
Gender
Female
Male
Properties:
hasSex (Human -> Gender)
So a Woman is
Human and hasGender some Female
My issue: When I display this ontology in Protégé, it automatically organizes Man and Woman as subclasses of Human, WITHOUT using a reasoner.
However, when I iterate over all classes in the OWL API and print their subclasses, only the asserted subclasses are found:
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Female>
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Woman>
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Male>
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Human>
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Gender>
<http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Female>
<http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Male>
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Man>
I need to use a reasoner to get the expected result, that Protégé shows without using one:
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Female>
Node( owl:Nothing )
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Woman>
Node( owl:Nothing )
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Male>
Node( owl:Nothing )
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Human>
Node( <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Man> )
Node( <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Woman> )
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Gender>
Node( <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Female> )
Node( <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Male> )
Subclasses of <http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Man>
Node( owl:Nothing )
What am I doing wrong here? Has Protégé some built-in rules for "clear" cases of subclasses? Where can I find them?
For reference, the example ontology and the OWL API code follow:
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Object Properties
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!-- http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#hasAge -->
<owl:ObjectProperty rdf:about="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#hasAge">
<rdfs:domain rdf:resource="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Human"/>
</owl:ObjectProperty>
<!-- http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#hasSex -->
<owl:ObjectProperty rdf:about="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#hasSex">
<rdfs:domain rdf:resource="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Human"/>
<rdfs:range rdf:resource="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Gender"/>
</owl:ObjectProperty>
<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Classes
//
///////////////////////////////////////////////////////////////////////////////////////
-->
<!-- http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Female -->
<owl:Class rdf:about="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Female">
<rdfs:subClassOf rdf:resource="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Gender"/>
</owl:Class>
<!-- http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Gender -->
<owl:Class rdf:about="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Gender"/>
<!-- http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Human -->
<owl:Class rdf:about="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Human"/>
<!-- http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Male -->
<owl:Class rdf:about="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Male">
<rdfs:subClassOf rdf:resource="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Gender"/>
</owl:Class>
<!-- http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Man -->
<owl:Class rdf:about="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Man">
<owl:equivalentClass>
<owl:Class>
<owl:intersectionOf rdf:parseType="Collection">
<rdf:Description rdf:about="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Human"/>
<owl:Restriction>
<owl:onProperty rdf:resource="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#hasSex"/>
<owl:someValuesFrom rdf:resource="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Male"/>
</owl:Restriction>
</owl:intersectionOf>
</owl:Class>
</owl:equivalentClass>
</owl:Class>
<!-- http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Woman -->
<owl:Class rdf:about="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Woman">
<owl:equivalentClass>
<owl:Class>
<owl:intersectionOf rdf:parseType="Collection">
<rdf:Description rdf:about="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Human"/>
<owl:Restriction>
<owl:onProperty rdf:resource="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#hasSex"/>
<owl:someValuesFrom rdf:resource="http://www.semanticweb.org/user/ontologies/2017/4/untitled-ontology-222#Female"/>
</owl:Restriction>
</owl:intersectionOf>
</owl:Class>
</owl:equivalentClass>
</owl:Class>
public static void main(String[] args) throws OWLOntologyCreationException {
OWLOntologyManager m = OWLManager.createOWLOntologyManager();
OWLOntology o = m.loadOntologyFromOntologyDocument(new File("testonto/Untitled.owl"));
OWLReasonerFactory reasonerFactory = new JFactFactory();
OWLReasoner reasoner = reasonerFactory.createReasoner(o);
o.classesInSignature().forEach(c -> {
System.out.println("Subclasses of " + c);
reasoner.getSubClasses(c, true).forEach(sc -> System.out.println(" " + sc));
// EntitySearcher.getSubClasses(c, o).forEach(sc -> System.out.println(" " + sc));
});
}
Short answer is yes, Protégé has some minimal reasoning to organise the asserted hierarchy.
I am currently building/modifying a larger ontology. As I had problems to define restrictions I build a very short example:
I have EuropeanCountry as a class and IslandCountry as a class:
<owl:Class rdf:about="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#EuropeanCountry">
<rdfs:subClassOf rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#Country"/>
</owl:Class>
<!-- http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#IslandCountry -->
<owl:Class rdf:about="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#IslandCountry">
<rdfs:subClassOf rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#Country"/>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#borders"/>
<owl:maxQualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">0</owl:maxQualifiedCardinality>
<owl:onClass rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#EuropeanCountry"/>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
As you can see I set a "maxQualifiedCardinality" restriction in Protege. If I create some individuals and (C1, C2 and Germany are EuropeanCountry, Island is IslandCountry) and relate them with the border property:
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#Island">
<rdf:type rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#IslandCountry"/>
<borders rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#C1"/>
<borders rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#C2"/>
<borders rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#Germany"/>
</owl:NamedIndividual>
I get an error thrown by Hermit reasoner that it is not allowed to set 3 neighbours to Island. If I now change the line
<owl:maxQualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:maxQualifiedCardinality>
to cardinality 1 I don't get any error if I set three neighbours as shown in the example.
Can anyone explain this and hopefully provide me a solution how I can write a restriction that one class should have x other classes (in this case how to write that Island should have 2 neighbours and a third one will throw an error by the reasoner)?
Thanks for your help and kind regards,
tanktoo
Edit:
I have now added all individuals to an AllDifferent:
<rdf:Description>
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#AllDifferent"/>
<owl:distinctMembers rdf:parseType="Collection">
<rdf:Description rdf:about="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#C1"/>
<rdf:Description rdf:about="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#C2"/>
<rdf:Description rdf:about="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#Germany"/>
</owl:distinctMembers>
</rdf:Description>
It is now working with the restriction above and the reasoner tells me that I am not allowed to set 3 border countries as maxCardinality is 1.
I have now changed my restriction to the following:
<owl:Class rdf:about="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#IslandCountry">
<rdfs:subClassOf rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#Country"/>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#borders"/>
<owl:minQualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">1</owl:minQualifiedCardinality>
<owl:onClass rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#EuropeanCountry"/>
</owl:Restriction>
</rdfs:subClassOf>
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#borders"/>
<owl:maxQualifiedCardinality rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">2</owl:maxQualifiedCardinality>
<owl:onClass rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#EuropeanCountry"/>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
I would now expect that the reasoner detects an error if I set less than 1 or more than 2 neighbours:
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/tanktoo
/ontologies/2016/10/untitled-ontology-81#Island">
<rdf:type rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#IslandCountry"/>
<borders rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#C1"/>
<borders rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#C2"/>
<borders rdf:resource="http://www.semanticweb.org/tanktoo/ontologies/2016/10/untitled-ontology-81#Germany"/>
</owl:NamedIndividual>
In this case the reasoner detects an errro because there are 3 neighbours. If I now delete all the neighbours so that Island border 0 countries the reasoner doesn't give me an error. Can someone explain me why?
Thanks for your help :)
I get an error thrown by Hermit reasoner that it is not allowed to set 3 neighbours to Island
If this is what the tool says, then it is a mistake. Granted, you are giving 3 names of bordering countries. But nothing says that these are names of 3 different countries. They could be several names of the same country, like "France", "Republic of France", "République française".
Since the reasoner has no way of knowing whether they are names of the same thing or not, it can't detect an inconsistency in the second case. However, in the first case, having at least a name for something means that there is strictly more than zero thing, so it makes sense that an inconsistency is detected.
If you'd like to make sure the reasoner detects when a country has more than 2 neighbours, then you'd have to explicitly say that the countries are different:
ex:C1 owl:differentFrom ex:C2, ex:Germany .
ex:C2 owl:differentFrom ex:Germany .
or:
[] a owl:AllDifferent;
owl:members ( ex:C1 ex:C2 ex:Germany ) .
In Protégé, in the Individual tab, you can specify from what an individual is different.
I'm new to this ontology. I m using protege now. I have 2 classes BT and Document. I have created 2 Object Property 1. topic (Domain:Document , Range:BT) 2. hasDocument (Inverse property of topic).
I have created 1 DataType Property called title (Domain:Document Range:Literal).
Following are the Samples for the properties which I have created
BT hasDocument Document
Document topic BT
Document title "TestingName"
I dont know how to create a property which infers the following result
BT newProperty "TestingName"
If I understand your question, you're looking to be able to infer from
docX topic someTopic
docX title "SampleTitle"
someTopic hasDocumentWithTitle "SampleTitle"
You could almost do this with an property chain, by asserting that hasDocumentWithTitle has as a subproperty the chain (inverse topic) o title. Unfortunately, in OWL property chains can't end with datatype properties, so you can't do this. However, you can use SWRL rules, and many OWL2 reasoners process SWRL rules. You'd use a rule of the form:
topic(?doc,?topic) ∧ title(?doc,?title) → hasDocumentWithTitle(?topic,?title)
For instance we can get the following result in Protege with the following ontology:
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rule-example="http://www.example.org/rule-example#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:swrl="http://www.w3.org/2003/11/swrl#"
xmlns:swrlb="http://www.w3.org/2003/11/swrlb#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:Ontology rdf:about="http://www.example.org/rule-example"/>
<owl:Class rdf:about="http://www.example.org/rule-example#Document"/>
<owl:Class rdf:about="http://www.example.org/rule-example#Topic"/>
<owl:ObjectProperty rdf:about="http://www.example.org/rule-example#hasTopic"/>
<owl:DatatypeProperty rdf:about="http://www.example.org/rule-example#hasTitle"/>
<owl:DatatypeProperty rdf:about="http://www.example.org/rule-example#hasDocumentWithTitle"/>
<owl:NamedIndividual rdf:about="http://www.example.org/rule-example#doc42">
<rdf:type rdf:resource="http://www.example.org/rule-example#Document"/>
<rule-example:hasTitle>Document Number Forty-Two</rule-example:hasTitle>
<rule-example:hasTopic>
<owl:NamedIndividual rdf:about="http://www.example.org/rule-example#topic101">
<rdf:type rdf:resource="http://www.example.org/rule-example#Topic"/>
<rule-example:hasTopic rdf:resource="http://www.example.org/rule-example#topic101"/>
</owl:NamedIndividual>
</rule-example:hasTopic>
</owl:NamedIndividual>
<swrl:Imp>
<swrl:head>
<swrl:AtomList>
<rdf:rest rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"/>
<rdf:first>
<swrl:DatavaluedPropertyAtom>
<swrl:propertyPredicate rdf:resource="http://www.example.org/rule-example#hasDocumentWithTitle"/>
<swrl:argument2>
<swrl:Variable rdf:about="urn:swrl#title"/>
</swrl:argument2>
<swrl:argument1>
<swrl:Variable rdf:about="urn:swrl#topic"/>
</swrl:argument1>
</swrl:DatavaluedPropertyAtom>
</rdf:first>
</swrl:AtomList>
</swrl:head>
<swrl:body>
<swrl:AtomList>
<rdf:rest>
<swrl:AtomList>
<rdf:rest rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"/>
<rdf:first>
<swrl:DatavaluedPropertyAtom>
<swrl:propertyPredicate rdf:resource="http://www.example.org/rule-example#hasTitle"/>
<swrl:argument1>
<swrl:Variable rdf:about="urn:swrl#doc"/>
</swrl:argument1>
<swrl:argument2 rdf:resource="urn:swrl#title"/>
</swrl:DatavaluedPropertyAtom>
</rdf:first>
</swrl:AtomList>
</rdf:rest>
<rdf:first>
<swrl:IndividualPropertyAtom>
<swrl:propertyPredicate rdf:resource="http://www.example.org/rule-example#hasTopic"/>
<swrl:argument1 rdf:resource="urn:swrl#doc"/>
<swrl:argument2 rdf:resource="urn:swrl#topic"/>
</swrl:IndividualPropertyAtom>
</rdf:first>
</swrl:AtomList>
</swrl:body>
</swrl:Imp>
</rdf:RDF>