org.semanticweb.HermiT.structural.ObjectPropertyInclusionManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.semanticweb.hermit Show documentation
Show all versions of org.semanticweb.hermit Show documentation
HermiT is reasoner for ontologies written using the Web Ontology Language (OWL). Given an OWL file, HermiT can determine whether or not the ontology is consistent, identify subsumption relationships between classes, and much more.
This is the maven build of HermiT and is designed for people who wish to use HermiT from within the OWL API. It is now versioned in the main HermiT version repository, although not officially supported by the HermiT developers.
The version number of this package is a composite of the HermiT version and a value representing the OWLAPI release it is compatible with. Note that the group id for the upstream HermiT is com.hermit-reasoner, while this fork is released under net.sourceforge.owlapi.
This fork exists to allow HermiT users to use newer OWLAPI versions than the ones supported by the original HermiT codebase.
This package includes the Jautomata library (http://jautomata.sourceforge.net/), and builds with it directly. This library appears to be no longer under active development, and so a "fork" seems appropriate. No development is intended or anticipated on this code base.
The newest version!
/* Copyright 2008, 2009, 2010 by the Oxford University Computing Laboratory
This file is part of HermiT.
HermiT is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
HermiT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with HermiT. If not, see .
*/
package org.semanticweb.HermiT.structural;
import java.util.*;
import org.semanticweb.HermiT.graph.Graph;
import org.semanticweb.HermiT.structural.OWLAxioms.ComplexObjectPropertyInclusion;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLIndividualAxiom;
import org.semanticweb.owlapi.model.OWLNegativeObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectCardinalityRestriction;
import org.semanticweb.owlapi.model.OWLObjectComplementOf;
import org.semanticweb.owlapi.model.OWLObjectHasSelf;
import org.semanticweb.owlapi.model.OWLObjectInverseOf;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import rationals.Automaton;
import rationals.State;
import rationals.Transition;
/**ObjectPropertyInclusionManager.*/
public class ObjectPropertyInclusionManager {
private static final String COULD_NOT_CREATE_AUTOMATON = "Could not create automaton";
protected final Map m_automataByProperty;
/**
* @param axioms axioms
*/
public ObjectPropertyInclusionManager(OWLAxioms axioms) {
m_automataByProperty=new HashMap<>();
createAutomata(m_automataByProperty,axioms.m_complexObjectPropertyExpressions,axioms.m_simpleObjectPropertyInclusions,axioms.m_complexObjectPropertyInclusions, axioms.m_explicitInverses);
}
/**
* @param factory factory
* @param axioms axioms
* @param _replacementIndex replacementIndex
* @return replacement index
*/
public int rewriteNegativeObjectPropertyAssertions(OWLDataFactory factory,OWLAxioms axioms,int _replacementIndex) {
int replacementIndex=_replacementIndex;
// now object property inclusion manager added all non-simple properties to axioms.m_complexObjectPropertyExpressions
// now that we know which roles are non-simple, we can decide which negative object property assertions have to be
// expressed as concept assertions so that transitivity rewriting applies properly. All new concepts for the concept
// assertions must be normalised, because we are done with the normal normalisation phase.
Set redundantFacts=new HashSet<>();
Set additionalFacts=new HashSet<>();
for (OWLIndividualAxiom axiom : axioms.m_facts) {
if (axiom instanceof OWLNegativeObjectPropertyAssertionAxiom) {
OWLNegativeObjectPropertyAssertionAxiom negAssertion=(OWLNegativeObjectPropertyAssertionAxiom)axiom;
OWLObjectPropertyExpression prop=negAssertion.getProperty();
if (axioms.m_complexObjectPropertyExpressions.contains(prop)) {
// turn not op(a b) into
// C(a) and not C or forall op not{b}
OWLIndividual individual=negAssertion.getObject();
// neg. op assertions cannot contain anonymous individuals
IRI iri = individual.asOWLNamedIndividual().getIRI();
OWLClass individualConcept=factory.getOWLClass(IRI.create("internal:nom#"+iri.getNamespace(), iri.getFragment()));
OWLClassExpression notIndividualConcept=factory.getOWLObjectComplementOf(individualConcept);
OWLClassExpression allNotIndividualConcept=factory.getOWLObjectAllValuesFrom(prop,notIndividualConcept);
OWLClassExpression definition=factory.getOWLClass(IRI.create("internal:def#","a"+(replacementIndex++)));
axioms.m_conceptInclusions.add(Arrays.asList(factory.getOWLObjectComplementOf(definition), allNotIndividualConcept));
additionalFacts.add(factory.getOWLClassAssertionAxiom(definition,negAssertion.getSubject()));
additionalFacts.add(factory.getOWLClassAssertionAxiom(individualConcept,individual));
redundantFacts.add(negAssertion);
}
}
}
axioms.m_facts.addAll(additionalFacts);
axioms.m_facts.removeAll(redundantFacts);
return replacementIndex;
}
/**
* @param dataFactory dataFactory
* @param axioms axioms
* @param _firstReplacementIndex firstReplacementIndex
*/
public void rewriteAxioms(OWLDataFactory dataFactory,OWLAxioms axioms,int _firstReplacementIndex) {
int firstReplacementIndex=_firstReplacementIndex;
// Check the asymmetric object properties for simplicity
for (OWLObjectPropertyExpression objectPropertyExpression : axioms.m_asymmetricObjectProperties)
if (axioms.m_complexObjectPropertyExpressions.contains(objectPropertyExpression))
throw new IllegalArgumentException("Non-simple property '"+objectPropertyExpression+"' or its inverse appears in asymmetric object property axiom.");
// Check the irreflexive object properties for simplicity
for (OWLObjectPropertyExpression objectPropertyExpression : axioms.m_irreflexiveObjectProperties)
if (axioms.m_complexObjectPropertyExpressions.contains(objectPropertyExpression))
throw new IllegalArgumentException("Non-simple property '"+objectPropertyExpression+"' or its inverse appears in irreflexive object property axiom.");
// Check the disjoint object properties for simplicity
axioms.m_disjointObjectProperties.forEach(c->c.forEach(p->{
if (axioms.m_complexObjectPropertyExpressions.contains(p))
throw new IllegalArgumentException("Non-simple property '"+p+"' or its inverse appears in disjoint properties axiom.");}));
// Check simple properties in the number restrictions and replace universals
Map replacedDescriptions=new HashMap<>();
for (List inclusion : axioms.m_conceptInclusions) {
for (int index=0;index replacement : replacedDescriptions.entrySet()) {
Automaton automaton=m_automataByProperty.get(replacement.getKey().getProperty());
boolean isOfNegativePolarity=(replacement.getValue() instanceof OWLObjectComplementOf);
// Generate states of the automaton
Map statesToConcepts=new HashMap<>();
for (Object stateObject : automaton.states()) {
State state=(State)stateObject;
if (state.isInitial())
statesToConcepts.put(state,replacement.getValue());
else {
OWLClassExpression stateConcept=dataFactory.getOWLClass(IRI.create("internal:all#","a"+(firstReplacementIndex++)));
if (isOfNegativePolarity)
stateConcept=stateConcept.getComplementNNF();
statesToConcepts.put(state,stateConcept);
}
}
// Generate the transitions
for (Object transitionObject : automaton.delta()) {
Transition transition=(Transition)transitionObject;
OWLClassExpression fromStateConcept=statesToConcepts.get(transition.start()).getComplementNNF();
OWLClassExpression toStateConcept=statesToConcepts.get(transition.end());
if (transition.label()==null)
axioms.m_conceptInclusions.add(Arrays.asList(fromStateConcept,toStateConcept));
else {
OWLObjectAllValuesFrom consequentAll=dataFactory.getOWLObjectAllValuesFrom((OWLObjectPropertyExpression)transition.label(),toStateConcept);
axioms.m_conceptInclusions.add(Arrays.asList(fromStateConcept,consequentAll));
}
}
// Generate the final states
OWLClassExpression filler=replacement.getKey().getFiller();
for (Object finalStateObject : automaton.terminals()) {
OWLClassExpression finalStateConceptComplement=statesToConcepts.get(finalStateObject).getComplementNNF();
if (filler.isOWLNothing())
axioms.m_conceptInclusions.add(Arrays.asList(finalStateConceptComplement));
else
axioms.m_conceptInclusions.add(Arrays.asList(finalStateConceptComplement,filler));
}
}
}
protected void createAutomata(Map automataByProperty,Set complexObjectPropertyExpressions,Collection> simpleObjectPropertyInclusions,Collection complexObjectPropertyInclusions,
Map> explicitInverses) {
Map> equivalentPropertiesMap=findEquivalentProperties(simpleObjectPropertyInclusions);
Set symmetricObjectProperties=findSymmetricProperties(simpleObjectPropertyInclusions);
Map> inversePropertiesMap=buildInversePropertiesMap(simpleObjectPropertyInclusions, explicitInverses);
Graph propertyDependencyGraph=buildPropertyOrdering(simpleObjectPropertyInclusions,complexObjectPropertyInclusions,equivalentPropertiesMap);
checkForRegularity(propertyDependencyGraph,equivalentPropertiesMap);
Graph complexPropertiesDependencyGraph=propertyDependencyGraph.clone();
Set transitiveProperties=new HashSet<>();
Map individualAutomata=buildIndividualAutomata(complexPropertiesDependencyGraph,complexObjectPropertyInclusions,equivalentPropertiesMap,transitiveProperties);
Set simpleProperties=findSimpleProperties(complexPropertiesDependencyGraph,individualAutomata);
propertyDependencyGraph.removeElements(simpleProperties);
complexPropertiesDependencyGraph.removeElements(simpleProperties);
complexObjectPropertyExpressions.addAll(complexPropertiesDependencyGraph.getElements());
for (List inclusion : simpleObjectPropertyInclusions) {
if (complexObjectPropertyExpressions.contains(inclusion.get(0)) && individualAutomata.containsKey(inclusion.get(1))) {
Automaton auto = individualAutomata.get(inclusion.get(1));
Transition transition = new Transition(auto.initials().iterator().next(),inclusion.get(0),auto.terminals().iterator().next());
auto.addTransition(transition, "Could not create automaton for property at the bottom of hierarchy (simple property).");
}
}
Set inverseOfComplexProperties = new HashSet<>();
for (OWLObjectPropertyExpression complexProp : complexObjectPropertyExpressions)
inverseOfComplexProperties.add(complexProp.getInverseProperty());
complexObjectPropertyExpressions.addAll(inverseOfComplexProperties);
connectAllAutomata(automataByProperty,propertyDependencyGraph,inversePropertiesMap,individualAutomata,symmetricObjectProperties,transitiveProperties);
Map individualAutomataForEquivRoles=new HashMap<>();
automataByProperty.forEach((propExprWithAutomaton, autoOfPropExpr)->{
for (OWLObjectPropertyExpression equivProp : equivalentPropertiesMap.getOrDefault(propExprWithAutomaton, Collections.emptySet())) {
if (!equivProp.equals(propExprWithAutomaton) && !automataByProperty.containsKey(equivProp)) {
Automaton automatonOfEquivalent=(Automaton)autoOfPropExpr.clone();
individualAutomataForEquivRoles.put(equivProp, automatonOfEquivalent);
simpleProperties.remove(equivProp);
complexObjectPropertyExpressions.add(equivProp);
}
OWLObjectPropertyExpression inverseEquivProp = equivProp.getInverseProperty();
if (!inverseEquivProp.equals(propExprWithAutomaton) && !automataByProperty.containsKey(inverseEquivProp)) {
Automaton automatonOfEquivalent=(Automaton)autoOfPropExpr.clone();
individualAutomataForEquivRoles.put(inverseEquivProp, getMirroredCopy(automatonOfEquivalent));
simpleProperties.remove(inverseEquivProp);
complexObjectPropertyExpressions.add(inverseEquivProp);
}
}
});
automataByProperty.putAll(individualAutomataForEquivRoles);
}
private static Set findSymmetricProperties(Collection> simpleObjectPropertyInclusions) {
Set symmetricProperties = new HashSet<>();
for (List inclusion : simpleObjectPropertyInclusions)
if (inclusion.get(1).getInverseProperty().equals(inclusion.get(0)) || inclusion.get(1).equals(inclusion.get(0).getInverseProperty())){
symmetricProperties.add(inclusion.get(0));
symmetricProperties.add(inclusion.get(0).getInverseProperty());
}
return symmetricProperties;
}
protected Map> buildInversePropertiesMap(Collection> simpleObjectPropertyInclusions, Map> explicitInverses) {
Map> 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> inclusionCandidates=new ArrayList<>();
for (List inclusion : simpleObjectPropertyInclusions) {
if(isInverseOf( inclusion.get(0)) ^ isInverseOf(inclusion.get(1))) {
inclusionCandidates.add(inclusion);
}
}
for (List inclusion : inclusionCandidates) {
OWLObjectPropertyExpression inverse0 = inclusion.get(0).getInverseProperty();
OWLObjectPropertyExpression inverse1 = inclusion.get(1).getInverseProperty();
if (inclusion.get(1) instanceof OWLObjectInverseOf) {
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) {
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 o1, OWLObjectPropertyExpression o2 ) {
for (List l : list) {
if(l.get(0).equals(o1) && l.get(1).equals(o2)) {
return true;
}
}
return false;
}
protected Map> findEquivalentProperties(Collection> simpleObjectPropertyInclusions) {
Graph propertyDependencyGraph=new Graph<>();
Map> equivalentObjectPropertiesMapping=new HashMap<>();
for (List inclusion : simpleObjectPropertyInclusions)
if (!inclusion.get(0).equals(inclusion.get(1)) && !inclusion.get(0).equals(inclusion.get(1).getInverseProperty()))
propertyDependencyGraph.addEdge(inclusion.get(0),inclusion.get(1));
propertyDependencyGraph.transitivelyClose();
for (OWLObjectPropertyExpression objExpr : propertyDependencyGraph.getElements()) {
if (propertyDependencyGraph.getSuccessors(objExpr).contains(objExpr) || propertyDependencyGraph.getSuccessors(objExpr).contains(objExpr.getInverseProperty())) {
Set equivPropertiesSet=new HashSet<>();
for (OWLObjectPropertyExpression succ : propertyDependencyGraph.getSuccessors(objExpr)) {
if (!succ.equals(objExpr) && (propertyDependencyGraph.getSuccessors(succ).contains(objExpr) || propertyDependencyGraph.getSuccessors(succ).contains(objExpr.getInverseProperty())))
equivPropertiesSet.add(succ);
}
equivalentObjectPropertiesMapping.put(objExpr,equivPropertiesSet);
}
}
return equivalentObjectPropertiesMapping;
}
protected Set findSimpleProperties(Graph complexPropertiesDependencyGraph,Map individualAutomata) {
Set simpleProperties=new HashSet<>();
Graph complexPropertiesDependencyGraphWithInverses=complexPropertiesDependencyGraph.clone();
for (OWLObjectPropertyExpression complexProperty1 : complexPropertiesDependencyGraph.getElements())
for (OWLObjectPropertyExpression complexProperty2 : complexPropertiesDependencyGraph.getSuccessors(complexProperty1))
complexPropertiesDependencyGraphWithInverses.addEdge(complexProperty1.getInverseProperty(),complexProperty2.getInverseProperty());
Graph invertedGraph=complexPropertiesDependencyGraphWithInverses.getInverse();
invertedGraph.transitivelyClose();
for (OWLObjectPropertyExpression properties : invertedGraph.getElements()) {
boolean hasComplexSubproperty=false;
for (OWLObjectPropertyExpression subDependingProperties : invertedGraph.getSuccessors(properties)) {
if (individualAutomata.containsKey(subDependingProperties) || individualAutomata.containsKey(subDependingProperties.getInverseProperty())) {
hasComplexSubproperty=true;
break;
}
}
if (!hasComplexSubproperty && !individualAutomata.containsKey(properties) && !individualAutomata.containsKey(properties.getInverseProperty()))
simpleProperties.add(properties);
}
return simpleProperties;
}
protected void connectAllAutomata(Map completeAutomata,Graph propertyDependencyGraph,Map> inversePropertiesMap,Map individualAutomata,Set symmetricObjectProperties, Set transitiveProperties) {
Graph transClosedGraph=propertyDependencyGraph.clone();
transClosedGraph.transitivelyClose();
Set propertiesToStartRecursion=new HashSet<>();
for (OWLObjectPropertyExpression owlProp : transClosedGraph.getElements())
if (transClosedGraph.getSuccessors(owlProp).isEmpty())
propertiesToStartRecursion.add(owlProp);
Graph inversePropertyDependencyGraph=propertyDependencyGraph.getInverse();
for (OWLObjectPropertyExpression superproperty : propertiesToStartRecursion)
buildCompleteAutomataForProperties(superproperty,inversePropertiesMap,individualAutomata,completeAutomata,inversePropertyDependencyGraph,symmetricObjectProperties,transitiveProperties);
individualAutomata.forEach((property,propertyAutomaton)->{
if (!completeAutomata.containsKey(property)) {
if ((completeAutomata.containsKey(property.getInverseProperty()) && inversePropertyDependencyGraph.getElements().contains(property.getInverseProperty())) || individualAutomata.containsKey(property.getInverseProperty())) {
Automaton inversePropertyAutomaton=completeAutomata.getOrDefault(property.getInverseProperty(), individualAutomata.get(property.getInverseProperty()));
increaseAutomatonWithInversePropertyAutomaton(propertyAutomaton,inversePropertyAutomaton);
}
completeAutomata.put(property,propertyAutomaton);
}
});
Map extraCompleteAutomataForInverseProperties=new HashMap<>();
completeAutomata.forEach((property,automaton)->{
if (!completeAutomata.containsKey(property.getInverseProperty()))
extraCompleteAutomataForInverseProperties.put(property.getInverseProperty(),getMirroredCopy(automaton));
});
completeAutomata.putAll(extraCompleteAutomataForInverseProperties);
extraCompleteAutomataForInverseProperties.clear();
completeAutomata.forEach((property,automaton)->{
if (!completeAutomata.containsKey(property.getInverseProperty())) {
extraCompleteAutomataForInverseProperties.put(property.getInverseProperty(),getMirroredCopy(automaton));
}
});
completeAutomata.putAll(extraCompleteAutomataForInverseProperties);
extraCompleteAutomataForInverseProperties.clear();
completeAutomata.forEach((propExprWithAutomaton, autoOfPropExpr)->{
for (OWLObjectPropertyExpression inverseProp : inversePropertiesMap.getOrDefault(propExprWithAutomaton, Collections.emptySet())) {
Automaton automatonOfInverse=completeAutomata.get(inverseProp);
if (automatonOfInverse!=null) {
increaseAutomatonWithInversePropertyAutomaton(autoOfPropExpr,automatonOfInverse);
extraCompleteAutomataForInverseProperties.put(propExprWithAutomaton,autoOfPropExpr);
}
else {
automatonOfInverse=getMirroredCopy(autoOfPropExpr);
extraCompleteAutomataForInverseProperties.put(inverseProp,automatonOfInverse);
}
}
});
completeAutomata.putAll(extraCompleteAutomataForInverseProperties);
}
protected void increaseAutomatonWithInversePropertyAutomaton(Automaton propertyAutomaton,Automaton inversePropertyAutomaton) {
State initialState=propertyAutomaton.initials().iterator().next();
State finalState=propertyAutomaton.terminals().iterator().next();
Transition transition=propertyAutomaton.deltaFrom(initialState,finalState).iterator().next();
automataConnector(propertyAutomaton,getMirroredCopy(inversePropertyAutomaton),transition);
}
protected Automaton buildCompleteAutomataForProperties(OWLObjectPropertyExpression propertyToBuildAutomatonFor,Map> inversePropertiesMap,Map individualAutomata,Map completeAutomata,Graph inversedPropertyDependencyGraph, Set symmetricObjectProperties, Set transitiveProperties) {
if (completeAutomata.containsKey(propertyToBuildAutomatonFor))
return completeAutomata.get(propertyToBuildAutomatonFor);
else if (completeAutomata.containsKey(propertyToBuildAutomatonFor.getInverseProperty()) && !individualAutomata.containsKey(propertyToBuildAutomatonFor)) {
Automaton mirroredCopy=getMirroredCopy(completeAutomata.get(propertyToBuildAutomatonFor.getInverseProperty()));
completeAutomata.put(propertyToBuildAutomatonFor,mirroredCopy);
return mirroredCopy;
}
//if the role has no (inv) sub-role which is complex and we need to completely construct its automaton
if (inversedPropertyDependencyGraph.getSuccessors(propertyToBuildAutomatonFor).isEmpty() && inversedPropertyDependencyGraph.getSuccessors(propertyToBuildAutomatonFor.getInverseProperty()).isEmpty()) {
Automaton automatonForLeafProperty=individualAutomata.get(propertyToBuildAutomatonFor);
//if the individual automaton for the role is empty
if (automatonForLeafProperty==null) {
Set inverses=inversePropertiesMap.get(propertyToBuildAutomatonFor);
boolean noInversePropertyWithAutomaton=true;
//if it has declared inverse roles
if (inverses!=null) {
for (OWLObjectPropertyExpression inverse : inverses)
if (individualAutomata.containsKey(inverse) && !inverse.equals(propertyToBuildAutomatonFor)) {
automatonForLeafProperty=getMirroredCopy(buildCompleteAutomataForProperties(inverse,inversePropertiesMap,individualAutomata,completeAutomata,inversedPropertyDependencyGraph, symmetricObjectProperties,transitiveProperties));
automatonForLeafProperty=minimizeAndNormalizeAutomaton(automatonForLeafProperty);
completeAutomata.put(propertyToBuildAutomatonFor,automatonForLeafProperty);
noInversePropertyWithAutomaton=false;
break;
}
}
//else if Inv(R) has an automaton
else if (individualAutomata.containsKey(propertyToBuildAutomatonFor.getInverseProperty())) {
automatonForLeafProperty=getMirroredCopy(buildCompleteAutomataForProperties(propertyToBuildAutomatonFor.getInverseProperty(),inversePropertiesMap,individualAutomata,completeAutomata,inversedPropertyDependencyGraph,symmetricObjectProperties,transitiveProperties));
if (!completeAutomata.containsKey(propertyToBuildAutomatonFor)) {
automatonForLeafProperty=minimizeAndNormalizeAutomaton(automatonForLeafProperty);
completeAutomata.put(propertyToBuildAutomatonFor,automatonForLeafProperty);
}
else
automatonForLeafProperty=completeAutomata.get(propertyToBuildAutomatonFor);
noInversePropertyWithAutomaton=false;
}
//if no inverse (either declared or Inv(R)) has an automaton
if (noInversePropertyWithAutomaton) {
automatonForLeafProperty=new Automaton();
State initial=automatonForLeafProperty.addState(true,false);
State accepting=automatonForLeafProperty.addState(false,true);
Transition transition = new Transition(initial,propertyToBuildAutomatonFor,accepting);
automatonForLeafProperty.addTransition(transition, "Could not create automaton for property at the bottom of hierarchy (simple property).");
finalizeConstruction(completeAutomata,propertyToBuildAutomatonFor,automatonForLeafProperty,symmetricObjectProperties,transitiveProperties);
}
}
else {
if (propertyToBuildAutomatonFor.getInverseProperty().isAnonymous() && individualAutomata.containsKey(propertyToBuildAutomatonFor.getInverseProperty())) {
Automaton inversePropertyAutomaton=buildCompleteAutomataForProperties(propertyToBuildAutomatonFor.getInverseProperty(),inversePropertiesMap,individualAutomata,completeAutomata,inversedPropertyDependencyGraph,symmetricObjectProperties,transitiveProperties);
increaseAutomatonWithInversePropertyAutomaton(automatonForLeafProperty,getMirroredCopy(inversePropertyAutomaton));
if (!completeAutomata.containsKey(propertyToBuildAutomatonFor))
finalizeConstruction(completeAutomata,propertyToBuildAutomatonFor,automatonForLeafProperty,symmetricObjectProperties,transitiveProperties);
else
automatonForLeafProperty=completeAutomata.get(propertyToBuildAutomatonFor);
}
else {
increaseWithDefinedInverseIfNecessary(propertyToBuildAutomatonFor,automatonForLeafProperty,inversePropertiesMap,individualAutomata);
finalizeConstruction(completeAutomata,propertyToBuildAutomatonFor,automatonForLeafProperty,symmetricObjectProperties,transitiveProperties);
}
}
return automatonForLeafProperty;
}
else {
Automaton biggerPropertyAutomaton=individualAutomata.get(propertyToBuildAutomatonFor);
if (biggerPropertyAutomaton==null) {
biggerPropertyAutomaton=new Automaton();
State initialState=biggerPropertyAutomaton.addState(true,false);
State finalState=biggerPropertyAutomaton.addState(false,true);
Transition transition=new Transition(initialState,propertyToBuildAutomatonFor,finalState);
biggerPropertyAutomaton.addTransition(transition, COULD_NOT_CREATE_AUTOMATON);
for (OWLObjectPropertyExpression smallerProperty : inversedPropertyDependencyGraph.getSuccessors(propertyToBuildAutomatonFor)) {
Automaton smallerPropertyAutomaton=buildCompleteAutomataForProperties(smallerProperty,inversePropertiesMap,individualAutomata,completeAutomata,inversedPropertyDependencyGraph,symmetricObjectProperties,transitiveProperties);
automataConnector(biggerPropertyAutomaton,smallerPropertyAutomaton,transition);
Transition t = new Transition(initialState,smallerProperty,finalState);
biggerPropertyAutomaton.addTransition(t, COULD_NOT_CREATE_AUTOMATON);
}
if (propertyToBuildAutomatonFor.getInverseProperty().isAnonymous() && individualAutomata.containsKey(propertyToBuildAutomatonFor.getInverseProperty())) {
Automaton inversePropertyAutomaton=buildCompleteAutomataForProperties(propertyToBuildAutomatonFor.getInverseProperty(),inversePropertiesMap,individualAutomata,completeAutomata,inversedPropertyDependencyGraph,symmetricObjectProperties,transitiveProperties);
increaseAutomatonWithInversePropertyAutomaton(biggerPropertyAutomaton,getMirroredCopy(inversePropertyAutomaton));
if (!completeAutomata.containsKey(propertyToBuildAutomatonFor))
finalizeConstruction(completeAutomata,propertyToBuildAutomatonFor,biggerPropertyAutomaton,symmetricObjectProperties,transitiveProperties);
else
biggerPropertyAutomaton=completeAutomata.get(propertyToBuildAutomatonFor);
}
else {
increaseWithDefinedInverseIfNecessary(propertyToBuildAutomatonFor,biggerPropertyAutomaton,inversePropertiesMap,individualAutomata);
if (!completeAutomata.containsKey(propertyToBuildAutomatonFor))
finalizeConstruction(completeAutomata,propertyToBuildAutomatonFor,biggerPropertyAutomaton,symmetricObjectProperties,transitiveProperties);
else
biggerPropertyAutomaton=completeAutomata.get(propertyToBuildAutomatonFor);
}
}
else {
for (OWLObjectPropertyExpression smallerProperty : inversedPropertyDependencyGraph.getSuccessors(propertyToBuildAutomatonFor)) {
boolean someInternalTransitionMatched=false;
for (Object transitionObject : biggerPropertyAutomaton.delta()) {
Transition transition=(Transition)transitionObject;
if (transition.label()!=null && transition.label().equals(smallerProperty)) {
Automaton smallerPropertyAutomaton=buildCompleteAutomataForProperties(smallerProperty,inversePropertiesMap,individualAutomata,completeAutomata,inversedPropertyDependencyGraph,symmetricObjectProperties,transitiveProperties);
if (smallerPropertyAutomaton.delta().size()!=1)
automataConnector(biggerPropertyAutomaton,smallerPropertyAutomaton,transition);
someInternalTransitionMatched=true;
}
}
if (!someInternalTransitionMatched) {
Automaton smallerPropertyAutomaton=buildCompleteAutomataForProperties(smallerProperty,inversePropertiesMap,individualAutomata,completeAutomata,inversedPropertyDependencyGraph,symmetricObjectProperties,transitiveProperties);
Transition initial2TerminalTransition=biggerPropertyAutomaton.deltaFrom(biggerPropertyAutomaton.initials().iterator().next(),biggerPropertyAutomaton.terminals().iterator().next()).iterator().next();
automataConnector(biggerPropertyAutomaton,smallerPropertyAutomaton,initial2TerminalTransition);
}
}
}
if (propertyToBuildAutomatonFor.getInverseProperty().isAnonymous() && individualAutomata.containsKey(propertyToBuildAutomatonFor.getInverseProperty())) {
Automaton inversePropertyAutomaton=buildCompleteAutomataForProperties(propertyToBuildAutomatonFor.getInverseProperty(),inversePropertiesMap,individualAutomata,completeAutomata,inversedPropertyDependencyGraph,symmetricObjectProperties,transitiveProperties);
increaseAutomatonWithInversePropertyAutomaton(biggerPropertyAutomaton,getMirroredCopy(inversePropertyAutomaton));
if (!completeAutomata.containsKey(propertyToBuildAutomatonFor))
finalizeConstruction(completeAutomata,propertyToBuildAutomatonFor,biggerPropertyAutomaton,symmetricObjectProperties,transitiveProperties);
else
biggerPropertyAutomaton=completeAutomata.get(propertyToBuildAutomatonFor);
}
else {
increaseWithDefinedInverseIfNecessary(propertyToBuildAutomatonFor,biggerPropertyAutomaton,inversePropertiesMap,individualAutomata);
if (!completeAutomata.containsKey(propertyToBuildAutomatonFor))
finalizeConstruction(completeAutomata,propertyToBuildAutomatonFor,biggerPropertyAutomaton,symmetricObjectProperties,transitiveProperties);
else
biggerPropertyAutomaton=completeAutomata.get(propertyToBuildAutomatonFor);
}
return biggerPropertyAutomaton;
}
}
private void finalizeConstruction(Map completeAutomata,OWLObjectPropertyExpression propertyToBuildAutomatonFor,Automaton biggerPropertyAutomaton,Set symmetricObjectProperties,Set transitiveProperties) {
if (transitiveProperties.contains(propertyToBuildAutomatonFor.getInverseProperty())) {
Transition transition = new Transition(biggerPropertyAutomaton.terminals().iterator().next(),null,biggerPropertyAutomaton.initials().iterator().next());
biggerPropertyAutomaton.addTransition(transition, "Could not create automaton for symmetric property: "+propertyToBuildAutomatonFor);
}
if (symmetricObjectProperties.contains (propertyToBuildAutomatonFor)) {
Transition basicTransition=new Transition(biggerPropertyAutomaton.initials().iterator().next(),propertyToBuildAutomatonFor.getInverseProperty(),biggerPropertyAutomaton.terminals().iterator().next());
automataConnector(biggerPropertyAutomaton,getMirroredCopy(biggerPropertyAutomaton),basicTransition);
}
Automaton bga=minimizeAndNormalizeAutomaton(biggerPropertyAutomaton);
completeAutomata.put(propertyToBuildAutomatonFor,bga);
completeAutomata.put(propertyToBuildAutomatonFor.getInverseProperty(),getMirroredCopy(bga));
}
protected void increaseWithDefinedInverseIfNecessary(OWLObjectPropertyExpression propertyToBuildAutomatonFor,Automaton leafPropertyAutomaton,Map> inversePropertiesMap,Map individualAutomata) {
Set inverses=inversePropertiesMap.get(propertyToBuildAutomatonFor);
if (inverses!=null) {
Automaton inversePropertyAutomaton=null;
for (OWLObjectPropertyExpression inverse : inverses) {
if (individualAutomata.containsKey(inverse) && !inverse.equals(propertyToBuildAutomatonFor)) {
inversePropertyAutomaton=individualAutomata.get(inverse);
increaseAutomatonWithInversePropertyAutomaton(leafPropertyAutomaton,inversePropertyAutomaton);
}
}
}
else if (individualAutomata.containsKey(propertyToBuildAutomatonFor.getInverseProperty())) {
Automaton autoOfInv_Role = individualAutomata.get(propertyToBuildAutomatonFor.getInverseProperty());
increaseAutomatonWithInversePropertyAutomaton(leafPropertyAutomaton,autoOfInv_Role);
}
}
protected Automaton minimizeAndNormalizeAutomaton(Automaton automaton) {
//This part of the code seemed to have a bug in an ontology given by Birte. The ontology created very large automata and was
//extremely difficult to see where the bug was exactly. Either the ToDFA class has a bug or due to state renaming that ToDFA does
//state names got mixed up later (a similar thing has happened before) however I could not detect something like that happening now.
//Without this code the automata are about double in size than with the code which can cause performance issues in ontologies with
//large and complex RIAs, which fortunately does not happen.
// Reducer minimizerDeterminizer=new Reducer();
// //if the automaton has more than 350-400 transitions it seems that the determiniser is very slow. In general this code does help to reduce the number of clauses produced.
// if( automaton.delta().size() > 300 )
// return automaton;
// Normalizer normalizer=new Normalizer();
// Automaton tempMinimizedAuto=minimizerDeterminizer.transform(automaton);
// if (tempMinimizedAuto.delta().size()>=automaton.delta().size())
// return automaton;
// if (tempMinimizedAuto.initials().size()!=1 || tempMinimizedAuto.terminals().size()!=1)
// tempMinimizedAuto=normalizer.transform(tempMinimizedAuto);
// if (tempMinimizedAuto.delta().size()>automaton.delta().size())
return automaton;
// return tempMinimizedAuto;
}
protected void useStandardAutomataConnector(Automaton biggerPropertyAutomaton,Automaton smallerPropertyAutomaton,Transition transition) {
Map stateMapper=getDisjointUnion(biggerPropertyAutomaton,smallerPropertyAutomaton);
State initialState=transition.start();
State finalState=transition.end();
State oldStartOfSmaller=stateMapper.get(smallerPropertyAutomaton.initials().iterator().next());
State oldFinalOfSmaller=stateMapper.get(smallerPropertyAutomaton.terminals().iterator().next());
Transition t1 = new Transition(initialState,null,oldStartOfSmaller);
Transition t2 = new Transition(oldFinalOfSmaller,null,finalState);
biggerPropertyAutomaton.addTransition(t1, "Could not build the Complete Automata of non-Simple Properties");
biggerPropertyAutomaton.addTransition(t2, "Could not build the Complete Automata of non-Simple Properties");
}
protected void automataConnector(Automaton biggerPropertyAutomaton,Automaton smallerPropertyAutomaton,Transition transition) {
useStandardAutomataConnector(biggerPropertyAutomaton,smallerPropertyAutomaton,transition);
}
protected Set deltaToState(Automaton smallerPropertyAutomaton,State state) {
Set incommingTrans=new HashSet<>();
for (Object transitionObject : smallerPropertyAutomaton.delta()) {
Transition transition=(Transition)transitionObject;
if (transition.end().equals(state))
incommingTrans.add(transition);
}
return incommingTrans;
}
protected Graph buildPropertyOrdering(Collection> simpleObjectPropertyInclusions,Collection complexObjectPropertyInclusions,Map> equivalentPropertiesMap) {
Graph propertyDependencyGraph=new Graph<>();
for (List inclusion : simpleObjectPropertyInclusions)
if (!inclusion.get(0).equals(inclusion.get(1)) && !inclusion.get(0).equals(inclusion.get(1).getInverseProperty()) && (equivalentPropertiesMap.get(inclusion.get(0))==null || !equivalentPropertiesMap.get(inclusion.get(0)).contains(inclusion.get(1))))
propertyDependencyGraph.addEdge(inclusion.get(0),inclusion.get(1));
for (OWLAxioms.ComplexObjectPropertyInclusion inclusion : complexObjectPropertyInclusions) {
OWLObjectPropertyExpression owlSuperProperty=inclusion.m_superObjectProperty;
OWLObjectPropertyExpression owlSubPropertyInChain=null;
OWLObjectPropertyExpression[] owlSubProperties=inclusion.m_subObjectProperties;
if (owlSubProperties.length!=2 && owlSuperProperty.equals(owlSubProperties[0]) && owlSuperProperty.equals(owlSubProperties[owlSubProperties.length-1]))
throw new IllegalArgumentException("The given property hierarchy is not regular.");
for (int i=0;i0 && i propertyDependencyGraph,Map> equivalentPropertiesMap) {
Graph regularityCheckGraph=propertyDependencyGraph.clone();
Graph regularityCheckGraphTemp;
boolean trimmed=false;
do {
trimmed=false;
regularityCheckGraphTemp=regularityCheckGraph.clone();
for (OWLObjectPropertyExpression prop : regularityCheckGraphTemp.getElements()) {
for (OWLObjectPropertyExpression succProp : regularityCheckGraphTemp.getSuccessors(prop)) {
if (equivalentPropertiesMap.containsKey(prop) && equivalentPropertiesMap.get(prop).contains(succProp)) {
for (OWLObjectPropertyExpression succPropSucc : regularityCheckGraphTemp.getSuccessors(succProp)) {
if (!prop.equals(succPropSucc))
regularityCheckGraph.addEdge(prop,succPropSucc);
}
trimmed=true;
regularityCheckGraph.getSuccessors(prop).remove(succProp);
}
}
}
} while (trimmed);
regularityCheckGraph.transitivelyClose();
for (OWLObjectPropertyExpression prop : regularityCheckGraph.getElements()) {
Set successors=regularityCheckGraph.getSuccessors(prop);
if (successors.contains(prop) || successors.contains(prop.getInverseProperty()))
throw new IllegalArgumentException("The given property hierarchy is not regular.\nThere is a cyclic dependency involving property "+prop);
}
}
protected Map buildIndividualAutomata(Graph complexPropertiesDependencyGraph,Collection complexObjectPropertyInclusions,Map> equivalentPropertiesMap,Set transitiveProperties) {
Map automataMap=new HashMap<>();
for (OWLAxioms.ComplexObjectPropertyInclusion inclusion : complexObjectPropertyInclusions) {
OWLObjectPropertyExpression[] subObjectProperties=inclusion.m_subObjectProperties;
OWLObjectPropertyExpression superObjectProperty=inclusion.m_superObjectProperty;
Automaton automaton=null;
State initialState=null;
State finalState=null;
if (!automataMap.containsKey(superObjectProperty)) {
automaton=new Automaton();
initialState=automaton.addState(true,false);
finalState=automaton.addState(false,true);
automaton.addTransition(new Transition(initialState,superObjectProperty,finalState), COULD_NOT_CREATE_AUTOMATON);
}
else {
automaton=automataMap.get(superObjectProperty);
initialState=automaton.initials().iterator().next();
finalState=automaton.terminals().iterator().next();
}
// RR->R
if (subObjectProperties.length==2 && subObjectProperties[0].equals(superObjectProperty) && subObjectProperties[1].equals(superObjectProperty)) {
automaton.addTransition(new Transition(finalState,null,initialState), COULD_NOT_CREATE_AUTOMATON);
transitiveProperties.add(superObjectProperty);
}
// R S2...Sn->R
else if (subObjectProperties[0].equals(superObjectProperty)) {
State fromState=finalState;
OWLObjectPropertyExpression transitionLabel;
for (int i=1;iR
else if (subObjectProperties[subObjectProperties.length-1].equals(superObjectProperty)) {
State fromState=initialState;
OWLObjectPropertyExpression transitionLabel;
for (int i=0;iR
else {
State fromState=initialState;
OWLObjectPropertyExpression transitionLabel;
for (int i=0;i getDisjointUnion(Automaton automaton1,Automaton automaton2) {
Map stateMapperUnionInverse=new HashMap<>();
for (Object stateObject : automaton2.states())
stateMapperUnionInverse.put((State)stateObject,automaton1.addState(false,false));
for (Object transitionObject : automaton2.delta()) {
Transition transition=(Transition)transitionObject;
automaton1.addTransition(new Transition(stateMapperUnionInverse.get(transition.start()),transition.label(),stateMapperUnionInverse.get(transition.end())), "Could not create disjoint union of automata");
}
return stateMapperUnionInverse;
}
protected Automaton getMirroredCopy(Automaton automaton) {
Automaton mirroredCopy=new Automaton();
Map map=new HashMap<>();
for (Object stateObject : automaton.states()) {
State state=(State)stateObject;
map.put(state,mirroredCopy.addState(state.isTerminal(),state.isInitial()));
}
for (Object transitionObject : automaton.delta()) {
Transition transition=(Transition)transitionObject;
Object label = transition.label();
if (label instanceof OWLObjectPropertyExpression) {
label = ((OWLObjectPropertyExpression)label).getInverseProperty();
}
mirroredCopy.addTransition(new Transition(map.get(transition.end()),label,map.get(transition.start())), null);
}
return mirroredCopy;
}
protected State addNewTransition(Automaton automaton,State fromState,OWLObjectPropertyExpression objectPropertyExpression) {
OWLObjectPropertyExpression propertyOfChain=objectPropertyExpression;
State toState=automaton.addState(false,false);
automaton.addTransition(new Transition(fromState,propertyOfChain,toState), COULD_NOT_CREATE_AUTOMATON);
return toState;
}
}