Skip to content

Commit

Permalink
Fix Inverses cause false property equivalences #3
Browse files Browse the repository at this point in the history
  • Loading branch information
ignazio1977 committed Sep 25, 2018
1 parent e63a0a2 commit b0b532b
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.semanticweb.owlapi.model.OWLClass;
Expand Down Expand Up @@ -51,7 +53,8 @@ public class OWLAxioms {
final Set<OWLObjectPropertyExpression> m_irreflexiveObjectProperties =new HashSet<>();
final Set<OWLObjectPropertyExpression> m_asymmetricObjectProperties =new HashSet<>();
final Collection<List<OWLDataPropertyExpression>> m_dataPropertyInclusions =new ArrayList<>();
final Collection<List<OWLDataPropertyExpression>> m_disjointDataProperties =new ArrayList<>();
final Collection<List<OWLDataPropertyExpression>> m_disjointDataProperties =new ArrayList<>();
final Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> m_explicitInverses = new HashMap<>();
final Collection<OWLIndividualAxiom> m_facts =new HashSet<>();
final Set<OWLHasKeyAxiom> m_hasKeys =new HashSet<>();
/** contains custom datatypes from DatatypeDefinition axioms*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,8 @@ public void visit(OWLDisjointObjectPropertiesAxiom axiom) {
public void visit(OWLInverseObjectPropertiesAxiom axiom) {
OWLObjectPropertyExpression first=axiom.getFirstProperty();
OWLObjectPropertyExpression second=axiom.getSecondProperty();
m_axioms.m_explicitInverses.computeIfAbsent(first, x->new HashSet<>()).add(second);
m_axioms.m_explicitInverses.computeIfAbsent(second, x->new HashSet<>()).add(first);
addInclusion(first,second.getInverseProperty());
addInclusion(second,first.getInverseProperty());
m_axioms.m_objectPropertiesOccurringInOWLAxioms.add(first.getNamedProperty());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class ObjectPropertyInclusionManager {
*/
public ObjectPropertyInclusionManager(OWLAxioms axioms) {
m_automataByProperty=new HashMap<>();
createAutomata(m_automataByProperty,axioms.m_complexObjectPropertyExpressions,axioms.m_simpleObjectPropertyInclusions,axioms.m_complexObjectPropertyInclusions);
createAutomata(m_automataByProperty,axioms.m_complexObjectPropertyExpressions,axioms.m_simpleObjectPropertyInclusions,axioms.m_complexObjectPropertyInclusions, axioms.m_explicitInverses);
}
/**
* @param factory factory
Expand Down Expand Up @@ -184,10 +184,11 @@ else if (classExpression instanceof OWLObjectHasSelf) {
}
}
}
protected void createAutomata(Map<OWLObjectPropertyExpression,Automaton> automataByProperty,Set<OWLObjectPropertyExpression> complexObjectPropertyExpressions,Collection<List<OWLObjectPropertyExpression>> simpleObjectPropertyInclusions,Collection<ComplexObjectPropertyInclusion> complexObjectPropertyInclusions) {
protected void createAutomata(Map<OWLObjectPropertyExpression,Automaton> automataByProperty,Set<OWLObjectPropertyExpression> complexObjectPropertyExpressions,Collection<List<OWLObjectPropertyExpression>> simpleObjectPropertyInclusions,Collection<ComplexObjectPropertyInclusion> complexObjectPropertyInclusions,
Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> explicitInverses) {
Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> equivalentPropertiesMap=findEquivalentProperties(simpleObjectPropertyInclusions);
Set<OWLObjectPropertyExpression> symmetricObjectProperties=findSymmetricProperties(simpleObjectPropertyInclusions);
Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> inversePropertiesMap=buildInversePropertiesMap(simpleObjectPropertyInclusions);
Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> inversePropertiesMap=buildInversePropertiesMap(simpleObjectPropertyInclusions, explicitInverses);
Graph<OWLObjectPropertyExpression> propertyDependencyGraph=buildPropertyOrdering(simpleObjectPropertyInclusions,complexObjectPropertyInclusions,equivalentPropertiesMap);
checkForRegularity(propertyDependencyGraph,equivalentPropertiesMap);

Expand Down Expand Up @@ -242,38 +243,53 @@ private static Set<OWLObjectPropertyExpression> findSymmetricProperties(Collecti
}
return symmetricProperties;
}
protected Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> buildInversePropertiesMap(Collection<List<OWLObjectPropertyExpression>> simpleObjectPropertyInclusions) {
Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> inversePropertiesMap=new HashMap<>();
for (List<OWLObjectPropertyExpression> inclusion : simpleObjectPropertyInclusions)
protected Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> buildInversePropertiesMap(Collection<List<OWLObjectPropertyExpression>> simpleObjectPropertyInclusions, Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> explicitInverses) {
Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> inversePropertiesMap=new HashMap<>(explicitInverses);
// Both inclusions must be found for an inverse relation to be built:
// a subproperty of inverse(b)
// b subproperty of inverse(a)
// implies
// a inverseOf b

// inverse(b) subproperty of a
// inverse(a) subproperty of b
// implies
// a inverseOf b (commutative, the order is unimportant)
List<List<OWLObjectPropertyExpression>> inclusionCandidates=new ArrayList<>();
for (List<OWLObjectPropertyExpression> inclusion : simpleObjectPropertyInclusions) {
if(isInverseOf( inclusion.get(0)) ^ isInverseOf(inclusion.get(1))) {
inclusionCandidates.add(inclusion);
}
}
for (List<OWLObjectPropertyExpression> inclusion : inclusionCandidates) {
OWLObjectPropertyExpression inverse0 = inclusion.get(0).getInverseProperty();
OWLObjectPropertyExpression inverse1 = inclusion.get(1).getInverseProperty();
if (inclusion.get(1) instanceof OWLObjectInverseOf) {
Set<OWLObjectPropertyExpression> inverseProperties=inversePropertiesMap.get(inclusion.get(0));
if (inverseProperties==null)
inverseProperties=new HashSet<>();
inverseProperties.add(inclusion.get(1).getInverseProperty());
inversePropertiesMap.put(inclusion.get(0),inverseProperties);

inverseProperties=inversePropertiesMap.get(inclusion.get(1).getInverseProperty());
if (inverseProperties==null)
inverseProperties=new HashSet<>();
inverseProperties.add(inclusion.get(0));
inversePropertiesMap.put(inclusion.get(1).getInverseProperty(),inverseProperties);

if(contains(inclusionCandidates, inverse1, inverse0)) {
inversePropertiesMap.computeIfAbsent(inclusion.get(0), x->new HashSet<>()).add(inverse1);
inversePropertiesMap.computeIfAbsent(inverse1, x->new HashSet<>()).add(inclusion.get(0));
}
}
else if (inclusion.get(0) instanceof OWLObjectInverseOf) {
Set<OWLObjectPropertyExpression> inverseProperties=inversePropertiesMap.get(inclusion.get(1));
if (inverseProperties==null)
inverseProperties=new HashSet<>();
inverseProperties.add(inclusion.get(0).getInverseProperty());
inversePropertiesMap.put(inclusion.get(1),inverseProperties);

inverseProperties=inversePropertiesMap.get(inclusion.get(0).getInverseProperty());
if (inverseProperties==null)
inverseProperties=new HashSet<>();
inverseProperties.add(inclusion.get(1));
inversePropertiesMap.put(inclusion.get(0).getInverseProperty(),inverseProperties);
if(contains(inclusionCandidates, inverse0, inverse1)) {
inversePropertiesMap.computeIfAbsent(inclusion.get(1), x->new HashSet<>()).add(inverse0);
inversePropertiesMap.computeIfAbsent(inverse0, x->new HashSet<>()).add(inclusion.get(1));
}
}
}
return inversePropertiesMap;
}
private static boolean isInverseOf(OWLObjectPropertyExpression e) {
return e instanceof OWLObjectInverseOf;
}
private static boolean contains(List<List<OWLObjectPropertyExpression>> list, OWLObjectPropertyExpression o1, OWLObjectPropertyExpression o2 ) {
for (List<OWLObjectPropertyExpression> l : list) {
if(l.get(0).equals(o1) && l.get(1).equals(o2)) {
return true;
}
}
return false;
}
protected Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> findEquivalentProperties(Collection<List<OWLObjectPropertyExpression>> simpleObjectPropertyInclusions) {
Graph<OWLObjectPropertyExpression> propertyDependencyGraph=new Graph<>();
Map<OWLObjectPropertyExpression,Set<OWLObjectPropertyExpression>> equivalentObjectPropertiesMapping=new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.semanticweb.HermiT.reasoner;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.junit.Test;
import org.semanticweb.HermiT.ReasonerFactory;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.io.StringDocumentSource;
import org.semanticweb.owlapi.model.*;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;

public class InverseAnonymousTest {
String input = "Prefix: : <http://example.org/>\n" + " Ontology: <http://asdf>\n"
+ " ObjectProperty: hasBigPart\n" + " SubPropertyOf: hasPart, inverse (partOf)\n"
+ " ObjectProperty: hasPart\n" + " InverseOf: partOf\n"
+ " ObjectProperty: partOf\n" + " InverseOf: hasPart";
OWLOntologyManager man = OWLManager.createOWLOntologyManager();
OWLDataFactory df = man.getOWLDataFactory();
OWLObjectProperty bigPart = df.getOWLObjectProperty(IRI.create("http://example.org/hasBigPart"));
OWLObjectProperty partOf = df.getOWLObjectProperty(IRI.create("http://example.org/partOf"));
OWLObjectProperty hasPart = df.getOWLObjectProperty(IRI.create("http://example.org/hasPart"));
OWLObjectPropertyExpression invPartOf = df.getOWLObjectInverseOf(partOf);
OWLObjectPropertyExpression invHasPart = df.getOWLObjectInverseOf(hasPart);
Set<OWLObjectPropertyExpression> expectedHasPart = new HashSet<>(Arrays.asList(invPartOf, hasPart));
Set<OWLObjectPropertyExpression> expectedPartOf = new HashSet<>(Arrays.asList(invHasPart, partOf));
Set<OWLObjectPropertyExpression> expectedBigPart = new HashSet<>(Arrays.asList(bigPart));

protected void assertExpectedEquivalencies(OWLReasoner reasoner) {
assertEquals(expectedBigPart, reasoner.getEquivalentObjectProperties(bigPart).getEntities());
assertEquals(expectedHasPart, reasoner.getEquivalentObjectProperties(hasPart).getEntities());
assertEquals(expectedPartOf, reasoner.getEquivalentObjectProperties(partOf).getEntities());
}

protected OWLReasoner reason(OWLOntology ont) {
OWLReasoner reasoner = new ReasonerFactory().createReasoner(ont);
return reasoner;
}

@Test
public void shouldFindBigPartSingletonWithoutTransitiveCharacteristic() throws OWLOntologyCreationException {
OWLOntology ont = man.loadOntologyFromOntologyDocument(new StringDocumentSource(input));
OWLReasoner reasoner = reason(ont);
assertExpectedEquivalencies(reasoner);
}

@Test
public void shouldFindBigPartSingletonWithTransitiveCharacteristic() throws OWLOntologyCreationException {
String in = input + "\n Characteristics: Transitive";
OWLOntology ont = man.loadOntologyFromOntologyDocument(new StringDocumentSource(in));
OWLReasoner reasoner = new ReasonerFactory().createReasoner(ont);
assertExpectedEquivalencies(reasoner);
}
}

0 comments on commit b0b532b

Please sign in to comment.