
org.semanticweb.HermiT.Reasoner 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;
import static org.semanticweb.owlapi.util.OWLAPIStreamUtils.*;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.semanticweb.HermiT.Configuration.BlockingStrategyType;
import org.semanticweb.HermiT.blocking.AncestorBlocking;
import org.semanticweb.HermiT.blocking.AnywhereBlocking;
import org.semanticweb.HermiT.blocking.AnywhereValidatedBlocking;
import org.semanticweb.HermiT.blocking.BlockingSignatureCache;
import org.semanticweb.HermiT.blocking.BlockingStrategy;
import org.semanticweb.HermiT.blocking.DirectBlockingChecker;
import org.semanticweb.HermiT.blocking.PairWiseDirectBlockingChecker;
import org.semanticweb.HermiT.blocking.SingleDirectBlockingChecker;
import org.semanticweb.HermiT.blocking.ValidatedPairwiseDirectBlockingChecker;
import org.semanticweb.HermiT.blocking.ValidatedSingleDirectBlockingChecker;
import org.semanticweb.HermiT.debugger.Debugger;
import org.semanticweb.HermiT.existentials.CreationOrderStrategy;
import org.semanticweb.HermiT.existentials.ExistentialExpansionStrategy;
import org.semanticweb.HermiT.existentials.IndividualReuseStrategy;
import org.semanticweb.HermiT.hierarchy.ClassificationProgressMonitor;
import org.semanticweb.HermiT.hierarchy.DeterministicClassification;
import org.semanticweb.HermiT.hierarchy.Hierarchy;
import org.semanticweb.HermiT.hierarchy.HierarchyDumperFSS;
import org.semanticweb.HermiT.hierarchy.HierarchyNode;
import org.semanticweb.HermiT.hierarchy.HierarchyPrinterFSS;
import org.semanticweb.HermiT.hierarchy.HierarchySearch;
import org.semanticweb.HermiT.hierarchy.InstanceManager;
import org.semanticweb.HermiT.hierarchy.QuasiOrderClassification;
import org.semanticweb.HermiT.hierarchy.QuasiOrderClassificationForRoles;
import org.semanticweb.HermiT.model.Atom;
import org.semanticweb.HermiT.model.AtomicConcept;
import org.semanticweb.HermiT.model.AtomicRole;
import org.semanticweb.HermiT.model.Constant;
import org.semanticweb.HermiT.model.DLOntology;
import org.semanticweb.HermiT.model.DescriptionGraph;
import org.semanticweb.HermiT.model.Equality;
import org.semanticweb.HermiT.model.Individual;
import org.semanticweb.HermiT.model.Inequality;
import org.semanticweb.HermiT.model.InverseRole;
import org.semanticweb.HermiT.model.Role;
import org.semanticweb.HermiT.monitor.TableauMonitor;
import org.semanticweb.HermiT.monitor.TableauMonitorFork;
import org.semanticweb.HermiT.monitor.Timer;
import org.semanticweb.HermiT.monitor.TimerWithPause;
import org.semanticweb.HermiT.structural.BuiltInPropertyManager;
import org.semanticweb.HermiT.structural.OWLAxioms;
import org.semanticweb.HermiT.structural.OWLAxiomsExpressivity;
import org.semanticweb.HermiT.structural.OWLClausification;
import org.semanticweb.HermiT.structural.OWLNormalization;
import org.semanticweb.HermiT.structural.ObjectPropertyInclusionManager;
import org.semanticweb.HermiT.structural.ReducedABoxOnlyClausification;
import org.semanticweb.HermiT.tableau.InterruptFlag;
import org.semanticweb.HermiT.tableau.ReasoningTaskDescription;
import org.semanticweb.HermiT.tableau.Tableau;
import org.semanticweb.owlapi.formats.PrefixDocumentFormat;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.AddOntologyAnnotation;
import org.semanticweb.owlapi.model.AxiomType;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnonymousIndividual;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLDataPropertyExpression;
import org.semanticweb.owlapi.model.OWLDatatype;
import org.semanticweb.owlapi.model.OWLDeclarationAxiom;
import org.semanticweb.owlapi.model.OWLDocumentFormat;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLIndividualAxiom;
import org.semanticweb.owlapi.model.OWLInverseFunctionalObjectPropertyAxiom;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLObjectComplementOf;
import org.semanticweb.owlapi.model.OWLObjectHasSelf;
import org.semanticweb.owlapi.model.OWLObjectHasValue;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyChange;
import org.semanticweb.owlapi.model.OWLOntologyChangeListener;
import org.semanticweb.owlapi.model.OWLSubObjectPropertyOfAxiom;
import org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom;
import org.semanticweb.owlapi.model.OWLTransitiveObjectPropertyAxiom;
import org.semanticweb.owlapi.model.RemoveAxiom;
import org.semanticweb.owlapi.model.RemoveOntologyAnnotation;
import org.semanticweb.owlapi.model.SWRLRule;
import org.semanticweb.owlapi.reasoner.BufferingMode;
import org.semanticweb.owlapi.reasoner.FreshEntitiesException;
import org.semanticweb.owlapi.reasoner.FreshEntityPolicy;
import org.semanticweb.owlapi.reasoner.InconsistentOntologyException;
import org.semanticweb.owlapi.reasoner.IndividualNodeSetPolicy;
import org.semanticweb.owlapi.reasoner.InferenceType;
import org.semanticweb.owlapi.reasoner.Node;
import org.semanticweb.owlapi.reasoner.NodeSet;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.reasoner.ReasonerInterruptedException;
import org.semanticweb.owlapi.reasoner.TimeOutException;
import org.semanticweb.owlapi.reasoner.impl.OWLClassNode;
import org.semanticweb.owlapi.reasoner.impl.OWLClassNodeSet;
import org.semanticweb.owlapi.reasoner.impl.OWLDataPropertyNode;
import org.semanticweb.owlapi.reasoner.impl.OWLDataPropertyNodeSet;
import org.semanticweb.owlapi.reasoner.impl.OWLNamedIndividualNode;
import org.semanticweb.owlapi.reasoner.impl.OWLNamedIndividualNodeSet;
import org.semanticweb.owlapi.reasoner.impl.OWLObjectPropertyNode;
import org.semanticweb.owlapi.reasoner.impl.OWLObjectPropertyNodeSet;
import org.semanticweb.owlapi.util.Version;
/**
* Answers queries about the logical implications of a particular knowledge base. A Reasoner is associated with a single knowledge base, which is "loaded" when the reasoner is constructed. By default a full classification of all atomic terms in the knowledge base is also performed at this time (which can take quite a while for large or complex ontologies), but this behavior can be disabled as a part of the Reasoner configuration. Internal details of the loading and reasoning algorithms can be configured in the Reasoner constructor and do not change over the lifetime of the Reasoner object---internal data structures and caches are optimized for a particular configuration. By default, HermiT will use the set of options which provide optimal performance.
*/
public class Reasoner implements OWLReasoner {
private static final Version version=new Version(1, 4, 1, 513);
private static final IRI PSEUDO_NOMINAL = IRI.create("internal:pseudo-nominal");
protected final OntologyChangeListener m_ontologyChangeListener;
protected final Configuration m_configuration;
protected final OWLOntology m_rootOntology;
protected final OWLDataFactory df;
protected final List m_pendingChanges;
protected final Collection m_descriptionGraphs;
protected final InterruptFlag m_interruptFlag;
protected ObjectPropertyInclusionManager m_objectPropertyInclusionManager;
protected DLOntology m_dlOntology;
protected Prefixes m_prefixes;
protected Tableau m_tableau;
protected Boolean m_isConsistent;
protected Hierarchy m_atomicConceptHierarchy;
protected Hierarchy m_objectRoleHierarchy;
protected Hierarchy m_dataRoleHierarchy;
protected Map>> m_directObjectRoleDomains;
protected Map>> m_directObjectRoleRanges;
protected Map>> m_directDataRoleDomains;
protected Map,Set>> m_directDisjointClasses;
protected InstanceManager m_instanceManager;
/**
* Creates a new reasoner object with the parameters for blocking, expansion strategy etc as specified in the given configuration object. A default configuration can be obtained by just passing new Configuration(). Then the given manager is used to find all required imports for the given ontology and the ontology with the imports is loaded into the reasoner and the data factory of the manager is used to create fresh concepts during the preprocessing phase if necessary.
*
* @param configuration
* - a configuration in which parameters can be defined such as the blocking strategy to be used etc
* @param rootOntology
* - the ontology that should be loaded by the reasoner
*/
public Reasoner(Configuration configuration,OWLOntology rootOntology) {
this(configuration,rootOntology,(Set)null);
}
/**
* Creates a new reasoner object loaded with the given ontology and the given description graphs. When creating the reasoner, the given configuration determines the parameters for blocking, expansion strategy etc. A default configuration can be obtained by just passing new Configuration(). Then the given manager is used to find all required imports for the given ontology and the ontology with the imports and the description graphs are loaded into the reasoner. The data factory of the manager is used to create fresh concepts during the preprocessing phase if necessary.
*
* @param configuration
* - a configuration in which parameters can be defined such as the blocking strategy to be used etc
* @param rootOntology
* - the ontology that should be loaded by the reasoner
* @param descriptionGraphs
* - a set of description graphs
*/
public Reasoner(Configuration configuration,OWLOntology rootOntology,Collection descriptionGraphs) {
m_ontologyChangeListener=new OntologyChangeListener();
m_configuration=configuration;
m_rootOntology=rootOntology;
df=m_rootOntology.getOWLOntologyManager().getOWLDataFactory();
m_pendingChanges=new ArrayList<>();
m_rootOntology.getOWLOntologyManager().addOntologyChangeListener(m_ontologyChangeListener);
if (descriptionGraphs==null)
m_descriptionGraphs=Collections.emptySet();
else
m_descriptionGraphs=descriptionGraphs;
m_interruptFlag=new InterruptFlag(configuration.individualTaskTimeout);
m_directDisjointClasses=new HashMap<>();
loadOntology();
}
// Life-cycle management methods
protected void loadOntology() {
clearState();
// Convert OWLOntology into DLOntology
OWLClausification clausifier=new OWLClausification(m_configuration);
Object[] result=clausifier.preprocessAndClausify(m_rootOntology,m_descriptionGraphs);
m_objectPropertyInclusionManager=(ObjectPropertyInclusionManager)result[0];
m_dlOntology=(DLOntology)result[1];
// Load the DLOntology
createPrefixes();
m_tableau=createTableau(m_interruptFlag,m_configuration,m_dlOntology,null,m_prefixes);
m_instanceManager=null;
}
protected void createPrefixes() {
m_prefixes=new Prefixes();
m_prefixes.declareSemanticWebPrefixes();
Set individualIRIs=new HashSet<>();
Set anonIndividualIRIs=new HashSet<>();
for (Individual individual : m_dlOntology.getAllIndividuals())
if (individual.isAnonymous())
addIRI(individual.getIRI(),anonIndividualIRIs);
else
addIRI(individual.getIRI(),individualIRIs);
m_prefixes.declareInternalPrefixes(individualIRIs,anonIndividualIRIs);
m_prefixes.declareDefaultPrefix(m_dlOntology.getOntologyIRI()+"#");
// declare prefixes as used in the ontology if possible
OWLDocumentFormat format=m_rootOntology.getOWLOntologyManager().getOntologyFormat(m_rootOntology);
if (format instanceof PrefixDocumentFormat) {
PrefixDocumentFormat prefixFormat=(PrefixDocumentFormat)format;
prefixFormat.getPrefixName2PrefixMap().forEach((prefixName,prefix)->{
if (m_prefixes.getPrefixName(prefix)==null)
try {
m_prefixes.declarePrefix(prefixName,prefix);
}
catch (@SuppressWarnings("unused") IllegalArgumentException e) {
// ignore
}
});
}
}
protected void addIRI(String uri,Set prefixIRIs) {
if (!Prefixes.isInternalIRI(uri)) {
int lastHash=uri.lastIndexOf('#');
if (lastHash!=-1) {
String prefixIRI=uri.substring(0,lastHash+1);
prefixIRIs.add(prefixIRI);
}
}
}
@Override
protected void finalize() {
dispose();
}
@Override
public void dispose() {
m_rootOntology.getOWLOntologyManager().removeOntologyChangeListener(m_ontologyChangeListener);
clearState();
m_interruptFlag.dispose();
}
protected void clearState() {
m_pendingChanges.clear();
m_dlOntology=null;
m_prefixes=null;
m_tableau=null;
m_isConsistent=null;
m_atomicConceptHierarchy=null;
m_objectRoleHierarchy=null;
m_dataRoleHierarchy=null;
m_directObjectRoleDomains=new HashMap<>();
m_directObjectRoleRanges=new HashMap<>();
m_directDataRoleDomains=new HashMap<>();
m_directDisjointClasses=new HashMap<>();
m_instanceManager=null;
}
@Override
public void interrupt() {
m_interruptFlag.interrupt();
}
/**
* @return data factory
*/
public OWLDataFactory getDataFactory() {
return df;
}
// Accessor methods of the OWL API
@Override
public String getReasonerName() {
return "HermiT";
}
@Override
public Version getReasonerVersion() {
return version;
}
@Override
public OWLOntology getRootOntology() {
return m_rootOntology;
}
@Override
public long getTimeOut() {
return m_configuration.individualTaskTimeout;
}
@Override
public IndividualNodeSetPolicy getIndividualNodeSetPolicy() {
return m_configuration.getIndividualNodeSetPolicy();
}
@Override
public FreshEntityPolicy getFreshEntityPolicy() {
return m_configuration.getFreshEntityPolicy();
}
// HermiT's accessor methods
/**
* @return prefixes
*/
public Prefixes getPrefixes() {
return m_prefixes;
}
/**
* @return DL ontology
*/
public DLOntology getDLOntology() {
return m_dlOntology;
}
/**
* @return configuration
*/
public Configuration getConfiguration() {
return m_configuration.clone();
}
// Ontology change management methods
protected class OntologyChangeListener implements OWLOntologyChangeListener {
@Override
public void ontologiesChanged(List extends OWLOntologyChange> changes) {
for (OWLOntologyChange change : changes)
if (!(change instanceof RemoveOntologyAnnotation || change instanceof AddOntologyAnnotation))
m_pendingChanges.add(change);
}
}
@Override
public BufferingMode getBufferingMode() {
return m_configuration.bufferChanges ? BufferingMode.BUFFERING : BufferingMode.NON_BUFFERING;
}
@Override
public Set getPendingAxiomAdditions() {
Set added=new HashSet<>();
for (OWLOntologyChange change : m_pendingChanges)
if (change instanceof AddAxiom)
added.add(change.getAxiom());
return added;
}
@Override
public Set getPendingAxiomRemovals() {
Set removed=new HashSet<>();
for (OWLOntologyChange change : m_pendingChanges)
if (change instanceof RemoveAxiom)
removed.add(change.getAxiom());
return removed;
}
@Override
public List getPendingChanges() {
return m_pendingChanges;
}
@Override
public void flush() {
if (!m_pendingChanges.isEmpty()) {
// check if we can only reload the ABox
if (canProcessPendingChangesIncrementally()) {
Set rootOntologyImportsClosure=asSet(m_rootOntology.importsClosure());
Set positiveFacts=m_dlOntology.getPositiveFacts();
Set negativeFacts=m_dlOntology.getNegativeFacts();
Set allIndividuals=new HashSet<>();
Set allAtomicConcepts=m_dlOntology.getAllAtomicConcepts();
Set allAtomicObjectRoles=m_dlOntology.getAllAtomicObjectRoles();
Set allAtomicDataRoles=m_dlOntology.getAllAtomicDataRoles();
ReducedABoxOnlyClausification aboxFactClausifier=new ReducedABoxOnlyClausification(m_configuration,allAtomicConcepts,allAtomicObjectRoles,allAtomicDataRoles);
for (OWLOntologyChange change : m_pendingChanges) {
if (rootOntologyImportsClosure.contains(change.getOntology())) {
OWLAxiom axiom=change.getAxiom();
if (axiom.isLogicalAxiom()) {
aboxFactClausifier.clausify((OWLIndividualAxiom)axiom);
if (change instanceof AddAxiom) {
positiveFacts.addAll(aboxFactClausifier.getPositiveFacts());
negativeFacts.addAll(aboxFactClausifier.getNegativeFacts());
}
else {
positiveFacts.removeAll(aboxFactClausifier.getPositiveFacts());
negativeFacts.removeAll(aboxFactClausifier.getNegativeFacts());
}
}
}
}
for (Atom atom : positiveFacts)
atom.getIndividuals(allIndividuals);
for (Atom atom : negativeFacts)
atom.getIndividuals(allIndividuals);
m_dlOntology=new DLOntology(m_dlOntology.getOntologyIRI(),m_dlOntology.getDLClauses(),positiveFacts,negativeFacts,allAtomicConcepts,allAtomicObjectRoles,m_dlOntology.getAllComplexObjectRoles(),allAtomicDataRoles,m_dlOntology.getAllUnknownDatatypeRestrictions(),m_dlOntology.getDefinedDatatypeIRIs(),allIndividuals,m_dlOntology.hasInverseRoles(),m_dlOntology.hasAtMostRestrictions(),m_dlOntology.hasNominals(),m_dlOntology.hasDatatypes());
m_tableau=new Tableau(m_interruptFlag,m_tableau.getTableauMonitor(),m_tableau.getExistentialsExpansionStrategy(),m_configuration.useDisjunctionLearning,m_dlOntology,null,m_configuration.parameters);
m_instanceManager=null;
m_isConsistent=null;
}
else
loadOntology();
m_pendingChanges.clear();
}
}
/**
* @return true if incremental
*/
public boolean canProcessPendingChangesIncrementally() {
Set rootOntologyImportsClosure=asSet(m_rootOntology.importsClosure());
for (OWLOntologyChange change : m_pendingChanges) {
if (rootOntologyImportsClosure.contains(change.getOntology())) {
if (m_dlOntology.hasNominals() || !m_dlOntology.getAllDescriptionGraphs().isEmpty())
return false;
if (!change.isAxiomChange())
return false;
OWLAxiom axiom=change.getAxiom();
if (axiom.isLogicalAxiom()) {
if (axiom instanceof OWLClassAssertionAxiom) {
// we can handle everything that results in positive or negative facts
// (C a) with C a named class, HasSelf, HasValue, negated named class, negated HasSelf, negatedHasValue
// all used names must already exist in the loaded ontology
OWLClassAssertionAxiom classAssertion=(OWLClassAssertionAxiom)axiom;
OWLIndividual individual=classAssertion.getIndividual();
if (!isDefined(individual))
return false;
OWLClassExpression classExpression=classAssertion.getClassExpression();
if (classExpression instanceof OWLClass) {
if (!(isDefined((OWLClass)classExpression) || Prefixes.isInternalIRI(((OWLClass)classExpression).getIRI().toString())))
return false;
} else if (classExpression instanceof OWLObjectHasSelf) {
OWLObjectProperty namedOP=((OWLObjectHasSelf)classExpression).getProperty().getNamedProperty();
if (!(isDefined(namedOP) || Prefixes.isInternalIRI(namedOP.getIRI().toString())))
return false;
} else if (classExpression instanceof OWLObjectHasValue) {
OWLObjectHasValue hasValue=(OWLObjectHasValue)classExpression;
OWLObjectProperty namedOP=hasValue.getProperty().getNamedProperty();
OWLIndividual filler=hasValue.getFiller();
if (!(isDefined(namedOP) || Prefixes.isInternalIRI(namedOP.getIRI().toString())) || !isDefined(filler))
return false;
} else if (classExpression instanceof OWLObjectComplementOf) {
OWLClassExpression negated=((OWLObjectComplementOf)classExpression).getOperand();
if (negated instanceof OWLClass) {
OWLClass cls=(OWLClass)negated;
if (!(isDefined(cls) || Prefixes.isInternalIRI(cls.getIRI().toString())))
return false;
} else if (negated instanceof OWLObjectHasSelf) {
OWLObjectHasSelf hasSelf=(OWLObjectHasSelf)negated;
OWLObjectProperty namedOP=hasSelf.getProperty().getNamedProperty();
if (!(isDefined(namedOP) || Prefixes.isInternalIRI(namedOP.getIRI().toString())))
return false;
} else if (negated instanceof OWLObjectHasValue) {
OWLObjectHasValue hasSelf=(OWLObjectHasValue)negated;
OWLObjectProperty namedOP=hasSelf.getProperty().getNamedProperty();
OWLIndividual filler=hasSelf.getFiller();
if (!(isDefined(namedOP) || Prefixes.isInternalIRI(namedOP.getIRI().toString())) || !isDefined(filler))
return false;
} else {
return false;
}
} else
return false;
} else if (!(axiom instanceof OWLIndividualAxiom)) {
return false;
}
} else if (axiom instanceof OWLDeclarationAxiom) {
OWLEntity entity=((OWLDeclarationAxiom)axiom).getEntity();
if (entity.isOWLClass() && !(isDefined((OWLClass)entity) || Prefixes.isInternalIRI(((OWLClass)entity).getIRI().toString())))
return false;
else if (entity.isOWLObjectProperty() && !(isDefined((OWLObjectProperty)entity) || Prefixes.isInternalIRI(((OWLObjectProperty)entity).getIRI().toString())))
return false;
else if (entity.isOWLDataProperty() && !(isDefined((OWLDataProperty)entity) || Prefixes.isInternalIRI(((OWLDataProperty)entity).getIRI().toString())))
return false;
}
}
}
return true;
}
// General inferences
/**
* @param owlClass owlClass
* @return true if defined
*/
public boolean isDefined(OWLClass owlClass) {
AtomicConcept atomicConcept=AtomicConcept.create(owlClass.getIRI().toString());
return
m_dlOntology.containsAtomicConcept(atomicConcept) ||
AtomicConcept.THING.equals(atomicConcept) ||
AtomicConcept.NOTHING.equals(atomicConcept);
}
/**
* @param owlIndividual owlIndividual
* @return true if defined
*/
public boolean isDefined(OWLIndividual owlIndividual) {
Individual individual;
if (owlIndividual.isAnonymous())
individual=Individual.createAnonymous(owlIndividual.asOWLAnonymousIndividual().getID().toString());
else
individual=Individual.create(owlIndividual.asOWLNamedIndividual().getIRI().toString());
return m_dlOntology.containsIndividual(individual);
}
/**
* @param owlObjectProperty owlObjectProperty
* @return true if defined
*/
public boolean isDefined(OWLObjectProperty owlObjectProperty) {
AtomicRole atomicRole=AtomicRole.create(owlObjectProperty.getIRI().toString());
return
m_dlOntology.containsObjectRole(atomicRole) ||
AtomicRole.TOP_OBJECT_ROLE.equals(atomicRole) ||
AtomicRole.BOTTOM_OBJECT_ROLE.equals(atomicRole);
}
/**
* @param owlDataProperty owlDataProperty
* @return true if defined
*/
public boolean isDefined(OWLDataProperty owlDataProperty) {
AtomicRole atomicRole=AtomicRole.create(owlDataProperty.getIRI().toString());
return
m_dlOntology.containsDataRole(atomicRole) ||
AtomicRole.TOP_DATA_ROLE.equals(atomicRole) ||
AtomicRole.BOTTOM_DATA_ROLE.equals(atomicRole);
}
@Override
public Set getPrecomputableInferenceTypes() {
Set supportedInferenceTypes=new HashSet<>();
supportedInferenceTypes.add(InferenceType.CLASS_HIERARCHY);
supportedInferenceTypes.add(InferenceType.OBJECT_PROPERTY_HIERARCHY);
supportedInferenceTypes.add(InferenceType.DATA_PROPERTY_HIERARCHY);
supportedInferenceTypes.add(InferenceType.CLASS_ASSERTIONS);
supportedInferenceTypes.add(InferenceType.OBJECT_PROPERTY_ASSERTIONS);
// supportedInferenceTypes.add(InferenceType.DATA_PROPERTY_ASSERTIONS);
supportedInferenceTypes.add(InferenceType.SAME_INDIVIDUAL);
// supportedInferenceTypes.add(InferenceType.DISJOINT_CLASSES);
return supportedInferenceTypes;
}
@Override
public boolean isPrecomputed(InferenceType inferenceType) {
switch (inferenceType) {
case CLASS_HIERARCHY:
return m_atomicConceptHierarchy!=null;
case OBJECT_PROPERTY_HIERARCHY:
return m_objectRoleHierarchy!=null;
case DATA_PROPERTY_HIERARCHY:
return m_dataRoleHierarchy!=null;
case CLASS_ASSERTIONS:
return m_instanceManager!=null && m_instanceManager.realizationCompleted();
case OBJECT_PROPERTY_ASSERTIONS:
return m_instanceManager!=null && m_instanceManager.objectPropertyRealizationCompleted();
// case DATA_PROPERTY_ASSERTIONS:
// return m_dataRoleHierarchy!=null; // used to find sub-propeties
case SAME_INDIVIDUAL:
return m_instanceManager!=null && m_instanceManager.sameAsIndividualsComputed();
case DATA_PROPERTY_ASSERTIONS:
case DIFFERENT_INDIVIDUALS:
// return false;
case DISJOINT_CLASSES:
// return m_atomicConceptHierarchy!=null && m_directDisjointClasses.keySet().size()==m_atomicConceptHierarchy.getAllElements().size()-2;
default:
break;
}
return false;
}
@Override
public void precomputeInferences(InferenceType... inferenceTypes) throws ReasonerInterruptedException,TimeOutException,InconsistentOntologyException {
checkPreConditions();
boolean doAll=m_configuration.prepareReasonerInferences==null;
// doAll is only false when used via Protege, in that case the Protege preferences apply
Set requiredInferences=new HashSet<>(Arrays.asList(inferenceTypes));
if (requiredInferences.contains(InferenceType.CLASS_HIERARCHY))
if (doAll || m_configuration.prepareReasonerInferences.classClassificationRequired)
classifyClasses();
if (requiredInferences.contains(InferenceType.OBJECT_PROPERTY_HIERARCHY))
if (doAll || m_configuration.prepareReasonerInferences.objectPropertyClassificationRequired)
classifyObjectProperties();
if (requiredInferences.contains(InferenceType.DATA_PROPERTY_HIERARCHY))
if (doAll || m_configuration.prepareReasonerInferences.dataPropertyClassificationRequired)
classifyDataProperties();
if (requiredInferences.contains(InferenceType.CLASS_ASSERTIONS))
if (doAll || m_configuration.prepareReasonerInferences.realisationRequired) {
realise();
if (m_configuration.individualNodeSetPolicy==IndividualNodeSetPolicy.BY_SAME_AS || (m_configuration.prepareReasonerInferences!=null && m_configuration.prepareReasonerInferences.sameAs))
precomputeSameAsEquivalenceClasses();
}
if (requiredInferences.contains(InferenceType.OBJECT_PROPERTY_ASSERTIONS))
if (doAll || m_configuration.prepareReasonerInferences.objectPropertyRealisationRequired)
realiseObjectProperties();
// if (requiredInferences.contains(InferenceType.DATA_PROPERTY_ASSERTIONS))
// if (doAll || m_configuration.prepareReasonerInferences.dataPropertyRealisationRequired)
// classifyDataProperties(); // used to enriched stated instances
if (requiredInferences.contains(InferenceType.SAME_INDIVIDUAL))
if (doAll || m_configuration.prepareReasonerInferences.sameAs)
precomputeSameAsEquivalenceClasses();
// the tasks is not being supported by HermiT because it would be very slow
// we silently ignore the request as the documentation of the method recommends
// if (requiredInferences.contains(InferenceType.DIFFERENT_INDIVIDUALS))
// throw new UnsupportedOperationException("Error: HermiT cannot precompute different individuals. "+System.getProperty("line.separator")+"That is a very expensive task because all pairs of individuals have to be tested despite the fact that such a test will most likely fail. ");
// if (requiredInferences.contains(InferenceType.DISJOINT_CLASSES))
// precomputeDisjointClasses();
}
protected void initialisePropertiesInstanceManager() {
if (m_instanceManager==null || !m_instanceManager.arePropertiesInitialised()) {
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStarted("Initializing property instance data structures");
if (m_instanceManager==null)
m_instanceManager=new InstanceManager(m_interruptFlag,this,m_atomicConceptHierarchy,m_objectRoleHierarchy);
boolean isConsistent=true;
if (m_isConsistent!=null && !m_isConsistent.booleanValue())
m_instanceManager.setInconsistent();
else {
int noAxioms=m_dlOntology.getDLClauses().size();
int noComplexRoles=m_dlOntology.getAllComplexObjectRoles().size();
if (m_dlOntology.hasInverseRoles())
noComplexRoles=noComplexRoles/2;
int noIndividuals=m_dlOntology.getAllIndividuals().size();
int chunks=((2*noComplexRoles*noIndividuals)/InstanceManager.thresholdForAdditionalAxioms)+1;
int stepsAdditionalAxioms=noComplexRoles*noIndividuals;
int stepsRewritingAdditionalAxioms=(5*noComplexRoles*noIndividuals)/chunks;
int stepsTableauExpansion=(stepsAdditionalAxioms/chunks)+noAxioms+noIndividuals;
int stepsInitialiseKnownPossible=noIndividuals+noComplexRoles*noIndividuals;
int steps=stepsAdditionalAxioms+(chunks*stepsRewritingAdditionalAxioms)+(chunks*stepsTableauExpansion)+stepsInitialiseKnownPossible;
int startIndividualIndex=0;
int completedSteps=0;
OWLAxiom[] additionalAxioms=m_instanceManager.getAxiomsForReadingOffCompexProperties(getDataFactory(),m_configuration.reasonerProgressMonitor,completedSteps,steps);
completedSteps+=stepsAdditionalAxioms/chunks;
boolean moreWork=true;
while (moreWork) {
Tableau tableau=getTableau(additionalAxioms);
completedSteps+=stepsRewritingAdditionalAxioms;
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskProgressChanged(completedSteps,steps);
isConsistent=tableau.isSatisfiable(true,true,null,null,null,null,m_instanceManager.getNodesForIndividuals(),new ReasoningTaskDescription(false,"Initial consistency check plus reading-off known and possible class and property instances (individual "+startIndividualIndex+" to "+m_instanceManager.getCurrentIndividualIndex()+")."));
completedSteps+=stepsTableauExpansion;
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskProgressChanged(completedSteps,steps);
if (!isConsistent) {
m_instanceManager.setInconsistent();
break;
}
else
completedSteps=m_instanceManager.initializeKnowAndPossiblePropertyInstances(m_configuration.reasonerProgressMonitor,startIndividualIndex,completedSteps,steps);
tableau.clearAdditionalDLOntology();
startIndividualIndex=m_instanceManager.getCurrentIndividualIndex();
additionalAxioms=m_instanceManager.getAxiomsForReadingOffCompexProperties(getDataFactory(),m_configuration.reasonerProgressMonitor,completedSteps,steps);
completedSteps+=stepsAdditionalAxioms/chunks;
moreWork=additionalAxioms.length>0;
}
if (m_isConsistent==null)
m_isConsistent=Boolean.valueOf(isConsistent);
}
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStopped();
}
}
protected void initialiseClassInstanceManager() {
if (m_instanceManager==null || !m_instanceManager.areClassesInitialised()) {
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStarted("Initializing class instance data structures");
if (m_instanceManager==null)
m_instanceManager=new InstanceManager(m_interruptFlag,this,m_atomicConceptHierarchy,m_objectRoleHierarchy);
boolean isConsistent=true;
if (m_isConsistent!=null && !m_isConsistent.booleanValue())
m_instanceManager.setInconsistent();
else {
int noAxioms=m_dlOntology.getDLClauses().size();
int noIndividuals=m_dlOntology.getAllIndividuals().size();
int stepsTableauExpansion=noAxioms+noIndividuals;
int stepsInitialiseKnownPossible=noIndividuals;
int steps=stepsTableauExpansion+stepsInitialiseKnownPossible;
int completedSteps=0;
Tableau tableau=getTableau();
isConsistent=tableau.isSatisfiable(true,true,null,null,null,null,m_instanceManager.getNodesForIndividuals(),new ReasoningTaskDescription(false,"Initial tableau for reading-off known and possible class instances."));
completedSteps+=stepsTableauExpansion;
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskProgressChanged(completedSteps,steps);
if (!isConsistent)
m_instanceManager.setInconsistent();
else
m_instanceManager.initializeKnowAndPossibleClassInstances(m_configuration.reasonerProgressMonitor,completedSteps,steps);
if (m_isConsistent==null)
m_isConsistent=Boolean.valueOf(isConsistent);
tableau.clearAdditionalDLOntology();
}
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStopped();
}
}
@Override
public boolean isConsistent() {
flushChangesIfRequired();
if (m_isConsistent==null)
m_isConsistent=Boolean.valueOf(getTableau().isSatisfiable(true,true,null,null,null,null,null,ReasoningTaskDescription.isABoxSatisfiable()));
return m_isConsistent.booleanValue();
}
@Override
public boolean isEntailmentCheckingSupported(AxiomType> axiomType) {
return true;
}
@Override
public boolean isEntailed(OWLAxiom axiom) {
checkPreConditions(axiom);
if (!isConsistent())
return true;
EntailmentChecker checker=new EntailmentChecker(this,getDataFactory());
return checker.entails(axiom);
}
@Override
public boolean isEntailed(Set extends OWLAxiom> axioms) {
checkPreConditions(axioms.toArray(new OWLObject[0]));
if (!m_isConsistent.booleanValue())
return true;
EntailmentChecker checker=new EntailmentChecker(this,getDataFactory());
return checker.entails(axioms);
}
// Concept inferences
/**
* Classify classes.
*/
public void classifyClasses() {
checkPreConditions();
if (m_atomicConceptHierarchy==null) {
Set relevantAtomicConcepts=new HashSet<>();
relevantAtomicConcepts.add(AtomicConcept.THING);
relevantAtomicConcepts.add(AtomicConcept.NOTHING);
for (AtomicConcept atomicConcept : m_dlOntology.getAllAtomicConcepts())
if (!Prefixes.isInternalIRI(atomicConcept.getIRI()))
relevantAtomicConcepts.add(atomicConcept);
if (!m_isConsistent.booleanValue())
m_atomicConceptHierarchy=Hierarchy.emptyHierarchy(relevantAtomicConcepts,AtomicConcept.THING,AtomicConcept.NOTHING);
else {
try {
final int numRelevantConcepts=relevantAtomicConcepts.size();
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStarted("Building the class hierarchy...");
ClassificationProgressMonitor progressMonitor=new ClassificationProgressMonitor() {
protected int m_processedConcepts=0;
@Override
public void elementClassified(AtomicConcept element) {
m_processedConcepts++;
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskProgressChanged(m_processedConcepts,numRelevantConcepts);
}
};
m_atomicConceptHierarchy=classifyAtomicConcepts(getTableau(),progressMonitor,AtomicConcept.THING,AtomicConcept.NOTHING,relevantAtomicConcepts,m_configuration.forceQuasiOrderClassification);
if (m_instanceManager!=null)
m_instanceManager.setToClassifiedConceptHierarchy(m_atomicConceptHierarchy);
}
finally {
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStopped();
}
}
}
}
@Override
public Node getTopClassNode() {
classifyClasses();
return atomicConceptHierarchyNodeToNode(m_atomicConceptHierarchy.getTopNode());
}
@Override
public Node getBottomClassNode() {
classifyClasses();
return atomicConceptHierarchyNodeToNode(m_atomicConceptHierarchy.getBottomNode());
}
@Override
public boolean isSatisfiable(OWLClassExpression classExpression) {
checkPreConditions(classExpression);
if (!isConsistent())
return false;
if (classExpression instanceof OWLClass && m_atomicConceptHierarchy!=null) {
AtomicConcept concept=H((OWLClass)classExpression);
HierarchyNode node=m_atomicConceptHierarchy.getNodeForElement(concept);
return node!=m_atomicConceptHierarchy.getBottomNode();
}
else {
OWLDataFactory factory=getDataFactory();
OWLIndividual freshIndividual=factory.getOWLAnonymousIndividual("fresh-individual");
OWLClassAssertionAxiom assertClassExpression=factory.getOWLClassAssertionAxiom(classExpression,freshIndividual);
Tableau tableau=getTableau(assertClassExpression);
return tableau.isSatisfiable(true,null,null,null,null,null,ReasoningTaskDescription.isConceptSatisfiable(classExpression));
}
}
protected boolean isSubClassOf(OWLClassExpression subClassExpression,OWLClassExpression superClassExpression) {
checkPreConditions(subClassExpression,superClassExpression);
if (!isConsistent() || subClassExpression.isOWLNothing() || superClassExpression.isOWLThing())
return true;
if (subClassExpression instanceof OWLClass && superClassExpression instanceof OWLClass) {
AtomicConcept subconcept=H((OWLClass)subClassExpression);
AtomicConcept superconcept=H((OWLClass)superClassExpression);
if (m_atomicConceptHierarchy!=null && !containsFreshEntities(subClassExpression,superClassExpression)) {
HierarchyNode subconceptNode=m_atomicConceptHierarchy.getNodeForElement(subconcept);
return subconceptNode.isEquivalentElement(superconcept) || subconceptNode.isAncestorElement(superconcept);
}
else {
Tableau tableau=getTableau();
Individual freshIndividual=Individual.createAnonymous("fresh-individual");
Atom subconceptAssertion=Atom.create(subconcept,freshIndividual);
Atom superconceptAssertion=Atom.create(superconcept,freshIndividual);
return !tableau.isSatisfiable(true,Collections.singleton(subconceptAssertion),Collections.singleton(superconceptAssertion),null,null,null,ReasoningTaskDescription.isConceptSubsumedBy(subconcept,superconcept));
}
}
else {
OWLDataFactory factory=getDataFactory();
OWLIndividual freshIndividual=factory.getOWLAnonymousIndividual("fresh-individual");
OWLClassAssertionAxiom assertSubClassExpression=factory.getOWLClassAssertionAxiom(subClassExpression,freshIndividual);
OWLClassAssertionAxiom assertNotSuperClassExpression=factory.getOWLClassAssertionAxiom(superClassExpression.getObjectComplementOf(),freshIndividual);
Tableau tableau=getTableau(assertSubClassExpression,assertNotSuperClassExpression);
boolean result=tableau.isSatisfiable(true,null,null,null,null,null,ReasoningTaskDescription.isConceptSubsumedBy(subClassExpression,superClassExpression));
tableau.clearAdditionalDLOntology();
return !result;
}
}
@Override
public Node getEquivalentClasses(OWLClassExpression classExpression) {
HierarchyNode node=getHierarchyNode(classExpression);
return atomicConceptHierarchyNodeToNode(node);
}
@Override
public NodeSet getSuperClasses(OWLClassExpression classExpression,boolean direct) {
HierarchyNode node=getHierarchyNode(classExpression);
Set> result;
if (direct)
result=node.getParentNodes();
else {
result=new HashSet<>(node.getAncestorNodes());
result.remove(node);
}
return atomicConceptHierarchyNodesToNodeSet(result);
}
@Override
public NodeSet getSubClasses(OWLClassExpression classExpression,boolean direct) {
HierarchyNode node=getHierarchyNode(classExpression);
Set> result;
if (direct)
result=node.getChildNodes();
else {
result=new HashSet<>(node.getDescendantNodes());
result.remove(node);
}
return atomicConceptHierarchyNodesToNodeSet(result);
}
@Override
public Node getUnsatisfiableClasses() {
classifyClasses();
HierarchyNode node=m_atomicConceptHierarchy.getBottomNode();
return atomicConceptHierarchyNodeToNode(node);
}
@Override
public NodeSet getDisjointClasses(OWLClassExpression classExpression) {
checkPreConditions(classExpression);
classifyClasses();
if (classExpression.isOWLNothing() || !m_isConsistent.booleanValue()) {
HierarchyNode node=m_atomicConceptHierarchy.getBottomNode();
return atomicConceptHierarchyNodesToNodeSet(node.getAncestorNodes());
}
else if (classExpression.isOWLThing()) {
HierarchyNode node=m_atomicConceptHierarchy.getBottomNode();
return atomicConceptHierarchyNodesToNodeSet(Collections.singleton(node));
}
else if (classExpression instanceof OWLClass) {
HierarchyNode node=getHierarchyNode(classExpression);
if (node==null || node==m_atomicConceptHierarchy.getTopNode()) {
// fresh concept
return new OWLClassNodeSet(getDataFactory().getOWLNothing());
}
else if (node==m_atomicConceptHierarchy.getBottomNode())
return atomicConceptHierarchyNodesToNodeSet(node.getAncestorNodes());
else {
Set> directDisjoints=getDisjointConceptNodes(node);
Set> result=new HashSet<>();
for (HierarchyNode directDisjoint : directDisjoints) {
result.addAll(directDisjoint.getDescendantNodes());
}
return atomicConceptHierarchyNodesToNodeSet(result);
}
}
else {
Node equivalentToComplement=getEquivalentClasses(classExpression.getObjectComplementOf());
NodeSet subsDisjoint=getSubClasses(classExpression.getObjectComplementOf(),false);
Set> result=new HashSet<>();
if (equivalentToComplement.getSize()>0)
result.add(equivalentToComplement);
add(result, subsDisjoint.nodes());
return new OWLClassNodeSet(result);
}
}
protected Set> getDisjointConceptNodes(HierarchyNode node) {
if (m_directDisjointClasses.containsKey(node))
return m_directDisjointClasses.get(node);
else {
OWLDataFactory factory=getDataFactory();
OWLClassExpression negated=factory.getOWLObjectComplementOf(factory.getOWLClass(IRI.create(node.getRepresentative().getIRI())));
HierarchyNode equivalentToComplement=getHierarchyNode(negated);
for (AtomicConcept equiv : equivalentToComplement.getEquivalentElements()) {
if (!Prefixes.isInternalIRI(equiv.getIRI())) {
HierarchyNode rootDisjoint=m_atomicConceptHierarchy.getNodeForElement(equiv);
Set> result=Collections.singleton(rootDisjoint);
m_directDisjointClasses.put(node,result);
return result;
}
}
Set> result=equivalentToComplement.getChildNodes();
m_directDisjointClasses.put(node,result);
return result;
}
}
/**
* Precompute disjoint classes.
*/
public void precomputeDisjointClasses() {
checkPreConditions();
if (!m_isConsistent.booleanValue())
return;
if (m_atomicConceptHierarchy==null || m_directDisjointClasses.size()> nodes=new HashSet<>(m_atomicConceptHierarchy.getAllNodes());
nodes.remove(m_atomicConceptHierarchy.getTopNode());
nodes.remove(m_atomicConceptHierarchy.getBottomNode());
nodes.removeAll(m_directDisjointClasses.keySet());
int steps=nodes.size();
int step=0;
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStarted("Compute disjoint classes");
for (HierarchyNode node : nodes) {
getDisjointConceptNodes(node);
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskProgressChanged(++step,steps);
}
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStopped();
}
}
protected HierarchyNode getHierarchyNode(OWLClassExpression classExpression) {
checkPreConditions(classExpression);
classifyClasses();
if (!isConsistent())
return m_atomicConceptHierarchy.getBottomNode();
else if (classExpression instanceof OWLClass) {
AtomicConcept atomicConcept=H((OWLClass)classExpression);
HierarchyNode node=m_atomicConceptHierarchy.getNodeForElement(atomicConcept);
if (node==null)
node=new HierarchyNode<>(atomicConcept,Collections.singleton(atomicConcept),Collections.singleton(m_atomicConceptHierarchy.getTopNode()),Collections.singleton(m_atomicConceptHierarchy.getBottomNode()));
return node;
}
else {
OWLDataFactory factory=getDataFactory();
OWLClass queryConcept=factory.getOWLClass(IRI.create("internal:query-concept"));
OWLAxiom classDefinitionAxiom=factory.getOWLEquivalentClassesAxiom(queryConcept,classExpression);
final Tableau tableau=getTableau(classDefinitionAxiom);
HierarchySearch.Relation hierarchyRelation=(parent, child) ->{
Individual freshIndividual=Individual.createAnonymous("fresh-individual");
return !tableau.isSatisfiable(true,Collections.singleton(Atom.create(child,freshIndividual)),null,null,Collections.singleton(Atom.create(parent,freshIndividual)),null,ReasoningTaskDescription.isConceptSubsumedBy(child,parent));
};
HierarchyNode extendedHierarchy=HierarchySearch.findPosition(hierarchyRelation,AtomicConcept.create("internal:query-concept"),m_atomicConceptHierarchy.getTopNode(),m_atomicConceptHierarchy.getBottomNode());
tableau.clearAdditionalDLOntology();
return extendedHierarchy;
}
}
// Object property inferences
/**
* Classify object Properties.
*/
public void classifyObjectProperties() {
checkPreConditions();
if (m_objectRoleHierarchy==null) {
Set relevantObjectRoles=new HashSet<>();
for (AtomicRole atomicRole : m_dlOntology.getAllAtomicObjectRoles()) {
if (atomicRole!=AtomicRole.TOP_OBJECT_ROLE && atomicRole!=AtomicRole.BOTTOM_OBJECT_ROLE) {
relevantObjectRoles.add(atomicRole);
if (m_dlOntology.hasInverseRoles())
relevantObjectRoles.add(atomicRole.getInverse());
}
}
if (!m_isConsistent.booleanValue()) {
relevantObjectRoles.add(AtomicRole.TOP_OBJECT_ROLE);
relevantObjectRoles.add(AtomicRole.BOTTOM_OBJECT_ROLE);
m_objectRoleHierarchy=Hierarchy.emptyHierarchy(relevantObjectRoles,AtomicRole.TOP_OBJECT_ROLE,AtomicRole.BOTTOM_OBJECT_ROLE);
}
else {
Map conceptsForRoles=new HashMap<>();
final Map rolesForConcepts=new HashMap<>();
// Create the additional axioms for classification
List additionalAxioms=new ArrayList<>();
OWLDataFactory factory=getDataFactory();
OWLClass freshConcept=factory.getOWLClass(IRI.create("internal:fresh-concept"));
for (Role objectRole : relevantObjectRoles) {
AtomicConcept conceptForRole;
OWLObjectPropertyExpression objectPropertyExpression;
if (objectRole instanceof AtomicRole) {
conceptForRole=AtomicConcept.create("internal:prop#"+((AtomicRole)objectRole).getIRI());
objectPropertyExpression=factory.getOWLObjectProperty(IRI.create(((AtomicRole)objectRole).getIRI()));
}
else {
conceptForRole=AtomicConcept.create("internal:prop#inv#"+((InverseRole)objectRole).getInverseOf().getIRI());
objectPropertyExpression=factory.getOWLObjectInverseOf(factory.getOWLObjectProperty(IRI.create(((InverseRole)objectRole).getInverseOf().getIRI())));
}
OWLAxiom axiom;
OWLClass classForRole=factory.getOWLClass(IRI.create(conceptForRole.getIRI()));
axiom=factory.getOWLEquivalentClassesAxiom(classForRole,factory.getOWLObjectSomeValuesFrom(objectPropertyExpression,freshConcept));
additionalAxioms.add(axiom);
conceptsForRoles.put(objectRole,conceptForRole);
rolesForConcepts.put(conceptForRole,objectRole);
}
// handle top & bottom case
conceptsForRoles.put(AtomicRole.TOP_OBJECT_ROLE,AtomicConcept.THING);
rolesForConcepts.put(AtomicConcept.THING,AtomicRole.TOP_OBJECT_ROLE);
conceptsForRoles.put(AtomicRole.BOTTOM_OBJECT_ROLE,AtomicConcept.NOTHING);
rolesForConcepts.put(AtomicConcept.NOTHING,AtomicRole.BOTTOM_OBJECT_ROLE);
OWLIndividual freshIndividual=factory.getOWLAnonymousIndividual();
OWLAxiom axiom=factory.getOWLClassAssertionAxiom(freshConcept,freshIndividual);
additionalAxioms.add(axiom);
OWLAxiom[] additionalAxiomsArray=new OWLAxiom[additionalAxioms.size()];
additionalAxioms.toArray(additionalAxiomsArray);
// Run the actual classification task
Tableau tableau=getTableau(additionalAxiomsArray);
try {
final int numberOfRoles=relevantObjectRoles.size();
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStarted("Classifying object properties...");
ClassificationProgressMonitor progressMonitor=new ClassificationProgressMonitor() {
protected int m_processedRoles=0;
@Override
public void elementClassified(AtomicConcept element) {
m_processedRoles++;
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskProgressChanged(m_processedRoles,numberOfRoles);
}
};
Hierarchy atomicConceptHierarchyForRoles=classifyAtomicConceptsForRoles(tableau,progressMonitor,conceptsForRoles.get(AtomicRole.TOP_OBJECT_ROLE),conceptsForRoles.get(AtomicRole.BOTTOM_OBJECT_ROLE),rolesForConcepts.keySet(),m_dlOntology.hasInverseRoles(),conceptsForRoles,rolesForConcepts,m_configuration.forceQuasiOrderClassification);
Hierarchy.Transformer transformer=new Hierarchy.Transformer() {
@Override
public Role transform(AtomicConcept atomicConcept) {
return rolesForConcepts.get(atomicConcept);
}
@Override
public Role determineRepresentative(AtomicConcept oldRepresentative,Set newEquivalentElements) {
return transform(oldRepresentative);
}
};
m_objectRoleHierarchy=atomicConceptHierarchyForRoles.transform(transformer,null);
if (m_instanceManager!=null)
m_instanceManager.setToClassifiedRoleHierarchy(m_objectRoleHierarchy);
}
finally {
tableau.clearAdditionalDLOntology();
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStopped();
}
}
}
}
@Override
public Node getTopObjectPropertyNode() {
classifyObjectProperties();
return objectPropertyHierarchyNodeToNode(m_objectRoleHierarchy.getTopNode());
}
@Override
public Node getBottomObjectPropertyNode() {
classifyObjectProperties();
return objectPropertyHierarchyNodeToNode(m_objectRoleHierarchy.getBottomNode());
}
protected boolean isSubObjectPropertyExpressionOf(OWLObjectPropertyExpression subObjectPropertyExpression,OWLObjectPropertyExpression superObjectPropertyExpression) {
checkPreConditions(subObjectPropertyExpression,superObjectPropertyExpression);
if (!m_isConsistent.booleanValue() || subObjectPropertyExpression.getNamedProperty().isOWLBottomObjectProperty() || superObjectPropertyExpression.getNamedProperty().isOWLTopObjectProperty())
return true;
Role subrole=H(subObjectPropertyExpression);
Role superrole=H(superObjectPropertyExpression);
if (m_objectRoleHierarchy!=null && !containsFreshEntities(subObjectPropertyExpression,superObjectPropertyExpression)) {
HierarchyNode subroleNode=m_objectRoleHierarchy.getNodeForElement(subrole);
return subroleNode.isEquivalentElement(superrole) || subroleNode.isAncestorElement(superrole);
}
else {
OWLDataFactory factory=getDataFactory();
OWLClass pseudoNominal=factory.getOWLClass(PSEUDO_NOMINAL);
OWLClassExpression allSuperNotPseudoNominal=factory.getOWLObjectAllValuesFrom(superObjectPropertyExpression,pseudoNominal.getObjectComplementOf());
OWLIndividual freshIndividualA=factory.getOWLAnonymousIndividual("fresh-individual-A");
OWLIndividual freshIndividualB=factory.getOWLAnonymousIndividual("fresh-individual-B");
OWLAxiom subObjectPropertyAssertion=factory.getOWLObjectPropertyAssertionAxiom(subObjectPropertyExpression,freshIndividualA,freshIndividualB);
OWLAxiom pseudoNominalAssertion=factory.getOWLClassAssertionAxiom(pseudoNominal,freshIndividualB);
OWLAxiom allSuperNotPseudoNominalAssertion=factory.getOWLClassAssertionAxiom(allSuperNotPseudoNominal,freshIndividualA);
Tableau tableau=getTableau(subObjectPropertyAssertion,pseudoNominalAssertion,allSuperNotPseudoNominalAssertion);
boolean result=tableau.isSatisfiable(true,null,null,null,null,null,ReasoningTaskDescription.isRoleSubsumedBy(subrole,superrole,true));
tableau.clearAdditionalDLOntology();
return !result;
}
}
protected boolean isSubObjectPropertyExpressionOf(List subPropertyChain,OWLObjectPropertyExpression superObjectPropertyExpression) {
OWLObject[] objects=new OWLObject[subPropertyChain.size()+1];
for (int i=0;i getSuperObjectProperties(OWLObjectPropertyExpression propertyExpression,boolean direct) {
HierarchyNode node=getHierarchyNode(propertyExpression);
if (direct)
return objectPropertyHierarchyNodesToNodeSet(node.getParentNodes());
Set> result=node.getAncestorNodes();
result.remove(node);
return objectPropertyHierarchyNodesToNodeSet(result);
}
@Override
public NodeSet getSubObjectProperties(OWLObjectPropertyExpression propertyExpression,boolean direct) {
HierarchyNode node=getHierarchyNode(propertyExpression);
if (direct)
return objectPropertyHierarchyNodesToNodeSet(node.getChildNodes());
Set> result=node.getDescendantNodes();
result.remove(node);
return objectPropertyHierarchyNodesToNodeSet(result);
}
@Override
public Node getEquivalentObjectProperties(OWLObjectPropertyExpression propertyExpression) {
return objectPropertyHierarchyNodeToNode(getHierarchyNode(propertyExpression));
}
@Override
public NodeSet getObjectPropertyDomains(OWLObjectPropertyExpression propertyExpression,boolean direct) {
checkPreConditions(propertyExpression);
classifyClasses();
if (!isConsistent())
return new OWLClassNodeSet(getBottomClassNode());
final Role role=H(propertyExpression);
Set> nodes=m_directObjectRoleDomains.get(role);
if (nodes==null) {
final Individual freshIndividualA=Individual.createAnonymous("fresh-individual-A");
final Individual freshIndividualB=Individual.createAnonymous("fresh-individual-B");
final Set roleAssertion=Collections.singleton(role.getRoleAssertion(freshIndividualA,freshIndividualB));
final Tableau tableau=getTableau();
HierarchySearch.SearchPredicate> searchPredicate=new HierarchySearch.SearchPredicate>() {
@Override
public Set> getSuccessorElements(HierarchyNode u) {
return u.getChildNodes();
}
@Override
public Set> getPredecessorElements(HierarchyNode u) {
return u.getParentNodes();
}
@Override
public boolean trueOf(HierarchyNode u) {
AtomicConcept potentialDomainConcept=u.getRepresentative();
return !tableau.isSatisfiable(false,roleAssertion,Collections.singleton(Atom.create(potentialDomainConcept,freshIndividualA)),null,null,null,ReasoningTaskDescription.isDomainOf(potentialDomainConcept,role));
}
};
nodes=HierarchySearch.search(searchPredicate,Collections.singleton(m_atomicConceptHierarchy.getTopNode()),null);
m_directObjectRoleDomains.put(role,nodes);
}
if (!direct)
nodes=HierarchyNode.getAncestorNodes(nodes);
return atomicConceptHierarchyNodesToNodeSet(nodes);
}
@Override
public NodeSet getObjectPropertyRanges(OWLObjectPropertyExpression propertyExpression,boolean direct) {
checkPreConditions(propertyExpression);
classifyClasses();
if (!isConsistent())
return new OWLClassNodeSet(getBottomClassNode());
final Role role=H(propertyExpression);
Set> nodes=m_directObjectRoleRanges.get(role);
if (nodes==null) {
final Individual freshIndividualA=Individual.createAnonymous("fresh-individual-A");
final Individual freshIndividualB=Individual.createAnonymous("fresh-individual-B");
final Set roleAssertion=Collections.singleton(role.getRoleAssertion(freshIndividualA,freshIndividualB));
final Tableau tableau=getTableau();
HierarchySearch.SearchPredicate> searchPredicate=new HierarchySearch.SearchPredicate>() {
@Override
public Set> getSuccessorElements(HierarchyNode u) {
return u.getChildNodes();
}
@Override
public Set> getPredecessorElements(HierarchyNode u) {
return u.getParentNodes();
}
@Override
public boolean trueOf(HierarchyNode u) {
AtomicConcept potentialRangeConcept=u.getRepresentative();
return !tableau.isSatisfiable(false,roleAssertion,Collections.singleton(Atom.create(potentialRangeConcept,freshIndividualB)),null,null,null,ReasoningTaskDescription.isRangeOf(potentialRangeConcept,role));
}
};
nodes=HierarchySearch.search(searchPredicate,Collections.singleton(m_atomicConceptHierarchy.getTopNode()),null);
m_directObjectRoleRanges.put(role,nodes);
}
if (!direct)
nodes=HierarchyNode.getAncestorNodes(nodes);
return atomicConceptHierarchyNodesToNodeSet(nodes);
}
@Override
public Node getInverseObjectProperties(OWLObjectPropertyExpression propertyExpression) {
return getEquivalentObjectProperties(propertyExpression.getInverseProperty());
}
@Override
public NodeSet getDisjointObjectProperties(OWLObjectPropertyExpression propertyExpression) {
checkPreConditions(propertyExpression);
if (!m_isConsistent.booleanValue())
return new OWLObjectPropertyNodeSet();
classifyObjectProperties();
Set> result=new HashSet<>();
if (propertyExpression.getNamedProperty().isOWLTopObjectProperty()) {
result.add(m_objectRoleHierarchy.getBottomNode());
return objectPropertyHierarchyNodesToNodeSet(result);
}
else if (propertyExpression.isOWLBottomObjectProperty()) {
HierarchyNode node=m_objectRoleHierarchy.getTopNode();
result.add(node);
result.addAll(node.getDescendantNodes());
return objectPropertyHierarchyNodesToNodeSet(result);
}
Role role=H(propertyExpression);
Individual freshIndividualA=Individual.createAnonymous("fresh-individual-A");
Individual freshIndividualB=Individual.createAnonymous("fresh-individual-B");
Atom roleAssertion=role.getRoleAssertion(freshIndividualA,freshIndividualB);
Tableau tableau=getTableau();
Set> nodesToTest=new HashSet<>();
nodesToTest.addAll(m_objectRoleHierarchy.getTopNode().getChildNodes());
while (!nodesToTest.isEmpty()) {
HierarchyNode nodeToTest=nodesToTest.iterator().next();
nodesToTest.remove(nodeToTest);
Role roleToTest=nodeToTest.getRepresentative();
Atom roleToTestAssertion=roleToTest.getRoleAssertion(freshIndividualA,freshIndividualB);
Set perTestAtoms=new HashSet<>(2);
perTestAtoms.add(roleAssertion);
perTestAtoms.add(roleToTestAssertion);
if (!tableau.isSatisfiable(false,perTestAtoms,null,null,null,null,new ReasoningTaskDescription(true,"disjointness of {0} and {1}",role,roleToTest)))
// disjoint
result.addAll(nodeToTest.getDescendantNodes());
else
// maybe some children are disjoint
nodesToTest.addAll(nodeToTest.getChildNodes());
}
if (result.isEmpty())
result.add(m_objectRoleHierarchy.getBottomNode());
return objectPropertyHierarchyNodesToNodeSet(result);
}
protected boolean isDisjointObjectProperty(OWLObjectPropertyExpression propertyExpression1,OWLObjectPropertyExpression propertyExpression2) {
checkPreConditions(propertyExpression1,propertyExpression2);
if (!m_isConsistent.booleanValue())
return true;
Role role1=H(propertyExpression1);
Role role2=H(propertyExpression2);
Individual freshIndividualA=Individual.createAnonymous("fresh-individual-A");
Individual freshIndividualB=Individual.createAnonymous("fresh-individual-B");
Atom roleAssertion1=role1.getRoleAssertion(freshIndividualA,freshIndividualB);
Atom roleAssertion2=role2.getRoleAssertion(freshIndividualA,freshIndividualB);
Set perTestAtoms=new HashSet<>(2);
perTestAtoms.add(roleAssertion1);
perTestAtoms.add(roleAssertion2);
return !getTableau().isSatisfiable(false,perTestAtoms,null,null,null,null,new ReasoningTaskDescription(true,"disjointness of {0} and {1}",role1,role2));
}
protected boolean isFunctional(OWLObjectPropertyExpression propertyExpression) {
checkPreConditions(propertyExpression);
if (!m_isConsistent.booleanValue())
return true;
Role role=H(propertyExpression);
Individual freshIndividual=Individual.createAnonymous("fresh-individual");
Individual freshIndividualA=Individual.createAnonymous("fresh-individual-A");
Individual freshIndividualB=Individual.createAnonymous("fresh-individual-B");
Set assertions=new HashSet<>();
assertions.add(role.getRoleAssertion(freshIndividual,freshIndividualA));
assertions.add(role.getRoleAssertion(freshIndividual,freshIndividualB));
assertions.add(Atom.create(Inequality.INSTANCE,freshIndividualA,freshIndividualB));
return !getTableau().isSatisfiable(false,assertions,null,null,null,null,new ReasoningTaskDescription(true,"functionality of {0}",role));
}
protected boolean isInverseFunctional(OWLObjectPropertyExpression propertyExpression) {
checkPreConditions(propertyExpression);
if (!m_isConsistent.booleanValue())
return true;
Role role=H(propertyExpression);
Individual freshIndividual=Individual.createAnonymous("fresh-individual");
Individual freshIndividualA=Individual.createAnonymous("fresh-individual-A");
Individual freshIndividualB=Individual.createAnonymous("fresh-individual-B");
Set assertions=new HashSet<>();
assertions.add(role.getRoleAssertion(freshIndividualA,freshIndividual));
assertions.add(role.getRoleAssertion(freshIndividualB,freshIndividual));
assertions.add(Atom.create(Inequality.INSTANCE,freshIndividualA,freshIndividualB));
return !getTableau().isSatisfiable(false,assertions,null,null,null,null,new ReasoningTaskDescription(true,"inverse-functionality of {0}",role));
}
protected boolean isIrreflexive(OWLObjectPropertyExpression propertyExpression) {
checkPreConditions(propertyExpression);
if (!m_isConsistent.booleanValue())
return true;
Role role=H(propertyExpression);
Individual freshIndividual=Individual.createAnonymous("fresh-individual");
return !getTableau().isSatisfiable(false,Collections.singleton(role.getRoleAssertion(freshIndividual,freshIndividual)),null,null,null,null,new ReasoningTaskDescription(true,"irreflexivity of {0}",role));
}
protected boolean isReflexive(OWLObjectPropertyExpression propertyExpression) {
checkPreConditions(propertyExpression);
if (!m_isConsistent.booleanValue())
return true;
OWLDataFactory factory=getDataFactory();
OWLClass pseudoNominal=factory.getOWLClass(PSEUDO_NOMINAL);
OWLClassExpression allNotPseudoNominal=factory.getOWLObjectAllValuesFrom(propertyExpression,pseudoNominal.getObjectComplementOf());
OWLIndividual freshIndividual=factory.getOWLAnonymousIndividual("fresh-individual");
OWLAxiom pseudoNominalAssertion=factory.getOWLClassAssertionAxiom(pseudoNominal,freshIndividual);
OWLAxiom allNotPseudoNominalAssertion=factory.getOWLClassAssertionAxiom(allNotPseudoNominal,freshIndividual);
Tableau tableau=getTableau(pseudoNominalAssertion,allNotPseudoNominalAssertion);
boolean result=tableau.isSatisfiable(true,null,null,null,null,null,new ReasoningTaskDescription(true,"symmetry of {0}",H(propertyExpression)));
tableau.clearAdditionalDLOntology();
return !result;
}
protected boolean isAsymmetric(OWLObjectPropertyExpression propertyExpression) {
checkPreConditions(propertyExpression);
if (!m_isConsistent.booleanValue())
return true;
OWLDataFactory factory=getDataFactory();
OWLIndividual freshIndividualA=factory.getOWLAnonymousIndividual("fresh-individual-A");
OWLIndividual freshIndividualB=factory.getOWLAnonymousIndividual("fresh-individual-B");
OWLAxiom assertion1=factory.getOWLObjectPropertyAssertionAxiom(propertyExpression,freshIndividualA,freshIndividualB);
OWLAxiom assertion2=factory.getOWLObjectPropertyAssertionAxiom(propertyExpression.getInverseProperty(),freshIndividualA,freshIndividualB);
Tableau tableau=getTableau(assertion1,assertion2);
boolean result=tableau.isSatisfiable(true,null,null,null,null,null,new ReasoningTaskDescription(true,"asymmetry of {0}",H(propertyExpression)));
tableau.clearAdditionalDLOntology();
return !result;
}
protected boolean isSymmetric(OWLObjectPropertyExpression propertyExpression) {
checkPreConditions(propertyExpression);
if (!m_isConsistent.booleanValue() || propertyExpression.getNamedProperty().isOWLTopObjectProperty())
return true;
OWLDataFactory factory=getDataFactory();
OWLClass pseudoNominal=factory.getOWLClass(PSEUDO_NOMINAL);
OWLClassExpression allNotPseudoNominal=factory.getOWLObjectAllValuesFrom(propertyExpression,pseudoNominal.getObjectComplementOf());
OWLIndividual freshIndividualA=factory.getOWLAnonymousIndividual("fresh-individual-A");
OWLIndividual freshIndividualB=factory.getOWLAnonymousIndividual("fresh-individual-B");
OWLAxiom assertion1=factory.getOWLObjectPropertyAssertionAxiom(propertyExpression,freshIndividualA,freshIndividualB);
OWLAxiom assertion2=factory.getOWLClassAssertionAxiom(allNotPseudoNominal,freshIndividualB);
OWLAxiom assertion3=factory.getOWLClassAssertionAxiom(pseudoNominal,freshIndividualA);
Tableau tableau=getTableau(assertion1,assertion2,assertion3);
boolean result=tableau.isSatisfiable(true,null,null,null,null,null,new ReasoningTaskDescription(true,"symmetry of {0}",propertyExpression));
tableau.clearAdditionalDLOntology();
return !result;
}
protected boolean isTransitive(OWLObjectPropertyExpression propertyExpression) {
checkPreConditions(propertyExpression);
if (!m_isConsistent.booleanValue())
return true;
OWLDataFactory factory=getDataFactory();
OWLClass pseudoNominal=factory.getOWLClass(PSEUDO_NOMINAL);
OWLClassExpression allNotPseudoNominal=factory.getOWLObjectAllValuesFrom(propertyExpression,pseudoNominal.getObjectComplementOf());
OWLIndividual freshIndividualA=factory.getOWLAnonymousIndividual("fresh-individual-A");
OWLIndividual freshIndividualB=factory.getOWLAnonymousIndividual("fresh-individual-B");
OWLIndividual freshIndividualC=factory.getOWLAnonymousIndividual("fresh-individual-C");
OWLAxiom assertion1=factory.getOWLObjectPropertyAssertionAxiom(propertyExpression,freshIndividualA,freshIndividualB);
OWLAxiom assertion2=factory.getOWLObjectPropertyAssertionAxiom(propertyExpression,freshIndividualB,freshIndividualC);
OWLAxiom assertion3=factory.getOWLClassAssertionAxiom(allNotPseudoNominal,freshIndividualA);
OWLAxiom assertion4=factory.getOWLClassAssertionAxiom(pseudoNominal,freshIndividualC);
Tableau tableau=getTableau(assertion1,assertion2,assertion3,assertion4);
boolean result=tableau.isSatisfiable(true,null,null,null,null,null,new ReasoningTaskDescription(true,"transitivity of {0}",H(propertyExpression)));
tableau.clearAdditionalDLOntology();
return !result;
}
protected HierarchyNode getHierarchyNode(OWLObjectPropertyExpression propertyExpression) {
checkPreConditions(propertyExpression);
classifyObjectProperties();
if (!m_isConsistent.booleanValue())
return m_objectRoleHierarchy.getBottomNode();
else {
Role role=H(propertyExpression);
HierarchyNode node=m_objectRoleHierarchy.getNodeForElement(role);
if (node==null)
node=new HierarchyNode<>(role,Collections.singleton(role),Collections.singleton(m_objectRoleHierarchy.getTopNode()),Collections.singleton(m_objectRoleHierarchy.getBottomNode()));
return node;
}
}
// Data property inferences
/**
* Classify data properties.
*/
public void classifyDataProperties() {
checkPreConditions();
if (m_dataRoleHierarchy==null) {
Set relevantDataRoles=new HashSet<>();
relevantDataRoles.add(AtomicRole.TOP_DATA_ROLE);
relevantDataRoles.add(AtomicRole.BOTTOM_DATA_ROLE);
relevantDataRoles.addAll(m_dlOntology.getAllAtomicDataRoles());
if (!m_isConsistent.booleanValue())
m_dataRoleHierarchy=Hierarchy.emptyHierarchy(relevantDataRoles,AtomicRole.TOP_DATA_ROLE,AtomicRole.BOTTOM_DATA_ROLE);
else {
if (m_dlOntology.hasDatatypes()) {
Map conceptsForRoles=new HashMap<>();
final Map rolesForConcepts=new HashMap<>();
// Create the additional axioms for classification
List additionalAxioms=new ArrayList<>();
OWLDataFactory factory=getDataFactory();
OWLDatatype unknownDatatypeA=factory.getOWLDatatype(IRI.create("internal:unknown-datatype#","A"));
for (AtomicRole dataRole : relevantDataRoles) {
AtomicConcept conceptForRole;
if (AtomicRole.TOP_DATA_ROLE.equals(dataRole))
conceptForRole=AtomicConcept.THING;
else if (AtomicRole.BOTTOM_DATA_ROLE.equals(dataRole))
conceptForRole=AtomicConcept.NOTHING;
else {
conceptForRole=AtomicConcept.create("internal:prop#"+dataRole.getIRI());
OWLClass classForRole=factory.getOWLClass(IRI.create(conceptForRole.getIRI()));
OWLDataProperty dataProperty=factory.getOWLDataProperty(IRI.create(dataRole.getIRI()));
OWLAxiom axiom=factory.getOWLEquivalentClassesAxiom(classForRole,factory.getOWLDataSomeValuesFrom(dataProperty,unknownDatatypeA));
additionalAxioms.add(axiom);
}
conceptsForRoles.put(dataRole,conceptForRole);
rolesForConcepts.put(conceptForRole,dataRole);
}
OWLAxiom[] additionalAxiomsArray=new OWLAxiom[additionalAxioms.size()];
additionalAxioms.toArray(additionalAxiomsArray);
// Run the actual classification task
Tableau tableau=getTableau(additionalAxiomsArray);
try {
final int numberOfRoles=relevantDataRoles.size();
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStarted("Classifying data properties...");
ClassificationProgressMonitor progressMonitor=new ClassificationProgressMonitor() {
protected int m_processedRoles=0;
@Override
public void elementClassified(AtomicConcept element) {
m_processedRoles++;
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskProgressChanged(m_processedRoles,numberOfRoles);
}
};
Hierarchy atomicConceptHierarchyForRoles=classifyAtomicConcepts(tableau,progressMonitor,conceptsForRoles.get(AtomicRole.TOP_DATA_ROLE),conceptsForRoles.get(AtomicRole.BOTTOM_DATA_ROLE),rolesForConcepts.keySet(),m_configuration.forceQuasiOrderClassification);
Hierarchy.Transformer transformer=new Hierarchy.Transformer() {
@Override
public AtomicRole transform(AtomicConcept atomicConcept) {
return rolesForConcepts.get(atomicConcept);
}
@Override
public AtomicRole determineRepresentative(AtomicConcept oldRepresentative,Set newEquivalentElements) {
return transform(oldRepresentative);
}
};
m_dataRoleHierarchy=atomicConceptHierarchyForRoles.transform(transformer,null);
}
finally {
tableau.clearAdditionalDLOntology();
if (m_configuration.reasonerProgressMonitor!=null)
m_configuration.reasonerProgressMonitor.reasonerTaskStopped();
}
}
else
m_dataRoleHierarchy=Hierarchy.trivialHierarchy(AtomicRole.TOP_DATA_ROLE,AtomicRole.BOTTOM_DATA_ROLE);
}
}
}
@Override
public Node getTopDataPropertyNode() {
classifyDataProperties();
return dataPropertyHierarchyNodeToNode(m_dataRoleHierarchy.getTopNode());
}
@Override
public Node getBottomDataPropertyNode() {
classifyDataProperties();
return dataPropertyHierarchyNodeToNode(m_dataRoleHierarchy.getBottomNode());
}
protected boolean isSubDataPropertyOf(OWLDataProperty subDataProperty,OWLDataProperty superDataProperty) {
checkPreConditions(subDataProperty,superDataProperty);
if (!m_isConsistent.booleanValue() || subDataProperty.isOWLBottomDataProperty() || superDataProperty.isOWLTopDataProperty())
return true;
AtomicRole subrole=H(subDataProperty);
AtomicRole superrole=H(superDataProperty);
if (m_dataRoleHierarchy!=null && !containsFreshEntities(subDataProperty,superDataProperty)) {
HierarchyNode subroleNode=m_dataRoleHierarchy.getNodeForElement(subrole);
return subroleNode.isEquivalentElement(superrole) || subroleNode.isAncestorElement(superrole);
}
else {
OWLDataFactory factory=getDataFactory();
OWLIndividual individual=factory.getOWLAnonymousIndividual("fresh-individual");
OWLLiteral freshConstant=factory.getOWLLiteral("internal:fresh-constant",factory.getOWLDatatype(IRI.create("internal:anonymous-constants")));
OWLDataProperty negatedSuperDataProperty=factory.getOWLDataProperty(IRI.create("internal:negated-superproperty"));
OWLAxiom subpropertyAssertion=factory.getOWLDataPropertyAssertionAxiom(subDataProperty,individual,freshConstant);
OWLAxiom negatedSuperpropertyAssertion=factory.getOWLDataPropertyAssertionAxiom(negatedSuperDataProperty,individual,freshConstant);
OWLAxiom superpropertyAxiomatization=factory.getOWLDisjointDataPropertiesAxiom(superDataProperty,negatedSuperDataProperty);
Tableau tableau=getTableau(subpropertyAssertion,negatedSuperpropertyAssertion,superpropertyAxiomatization);
boolean result=tableau.isSatisfiable(true,null,null,null,null,null,ReasoningTaskDescription.isRoleSubsumedBy(subrole,superrole,false));
tableau.clearAdditionalDLOntology();
return !result;
}
}
@Override
public NodeSet getSuperDataProperties(OWLDataProperty property,boolean direct) {
HierarchyNode node=getHierarchyNode(property);
Set> result;
if (direct)
result=node.getParentNodes();
else {
result=new HashSet<>(node.getAncestorNodes());
result.remove(node);
}
return dataPropertyHierarchyNodesToNodeSet(result);
}
@Override
public NodeSet getSubDataProperties(OWLDataProperty property,boolean direct) {
HierarchyNode node=getHierarchyNode(property);
Set> result;
if (direct)
result=node.getChildNodes();
else {
result=new HashSet<>(node.getDescendantNodes());
result.remove(node);
}
return dataPropertyHierarchyNodesToNodeSet(result);
}
@Override
public Node getEquivalentDataProperties(OWLDataProperty property) {
return dataPropertyHierarchyNodeToNode(getHierarchyNode(property));
}
@Override
public NodeSet getDataPropertyDomains(OWLDataProperty property,boolean direct) {
checkPreConditions(property);
classifyClasses();
if (!m_isConsistent.booleanValue())
return new OWLClassNodeSet(getBottomClassNode());
final AtomicRole atomicRole=H(property);
Set> nodes=m_directDataRoleDomains.get(atomicRole);
if (nodes==null) {
final Individual freshIndividual=Individual.createAnonymous("fresh-individual");
final Constant freshConstant=Constant.createAnonymous("fresh-constant");
final Set roleAssertion=Collections.singleton(atomicRole.getRoleAssertion(freshIndividual,freshConstant));
final Tableau tableau=getTableau();
HierarchySearch.SearchPredicate> searchPredicate=new HierarchySearch.SearchPredicate>() {
@Override
public Set> getSuccessorElements(HierarchyNode u) {
return u.getChildNodes();
}
@Override
public Set> getPredecessorElements(HierarchyNode u) {
return u.getParentNodes();
}
@Override
public boolean trueOf(HierarchyNode u) {
AtomicConcept potentialDomainConcept=u.getRepresentative();
return !tableau.isSatisfiable(false,roleAssertion,Collections.singleton(Atom.create(potentialDomainConcept,freshIndividual)),null,null,null,ReasoningTaskDescription.isDomainOf(potentialDomainConcept,atomicRole));
}
};
nodes=HierarchySearch.search(searchPredicate,Collections.singleton(m_atomicConceptHierarchy.getTopNode()),null);
m_directDataRoleDomains.put(atomicRole,nodes);
}
if (!direct)
nodes=HierarchyNode.getAncestorNodes(nodes);
return atomicConceptHierarchyNodesToNodeSet(nodes);
}
@Override
public NodeSet getDisjointDataProperties(OWLDataPropertyExpression propertyExpression) {
checkPreConditions(propertyExpression);
if (m_dlOntology.hasDatatypes()) {
classifyDataProperties();
if (!m_isConsistent.booleanValue())
return new OWLDataPropertyNodeSet();
Set> result=new HashSet<>();
if (propertyExpression.isOWLTopDataProperty()) {
result.add(m_dataRoleHierarchy.getBottomNode());
return dataPropertyHierarchyNodesToNodeSet(result);
}
else if (propertyExpression.isOWLBottomDataProperty()) {
HierarchyNode node=m_dataRoleHierarchy.getTopNode();
result.add(node);
result.addAll(node.getDescendantNodes());
return dataPropertyHierarchyNodesToNodeSet(result);
}
AtomicRole atomicRole=H(propertyExpression.asOWLDataProperty());
Individual freshIndividual=Individual.create("fresh-individual");
Constant freshConstant=Constant.createAnonymous("fresh-constant");
Atom atomicRoleAssertion=atomicRole.getRoleAssertion(freshIndividual,freshConstant);
Tableau tableau=getTableau();
Set> nodesToTest=new HashSet<>();
nodesToTest.addAll(m_dataRoleHierarchy.getTopNode().getChildNodes());
while (!nodesToTest.isEmpty()) {
HierarchyNode nodeToTest=nodesToTest.iterator().next();
nodesToTest.remove(nodeToTest);
AtomicRole atomicRoleToTest=nodeToTest.getRepresentative();
Atom atomicRoleToTestAssertion=atomicRoleToTest.getRoleAssertion(freshIndividual,freshConstant);
Set perTestAtoms=new HashSet<>(2);
perTestAtoms.add(atomicRoleAssertion);
perTestAtoms.add(atomicRoleToTestAssertion);
if (!tableau.isSatisfiable(false,perTestAtoms,null,null,null,null,new ReasoningTaskDescription(true,"disjointness of {0} and {1}",atomicRole,atomicRoleToTest)))
// disjoint
result.addAll(nodeToTest.getDescendantNodes());
else
// maybe some children are disjoint
nodesToTest.addAll(nodeToTest.getChildNodes());
}
if (result.isEmpty())
result.add(m_dataRoleHierarchy.getBottomNode());
return dataPropertyHierarchyNodesToNodeSet(result);
}
else {
OWLDataFactory factory=getDataFactory();
if (propertyExpression.isOWLTopDataProperty() && isConsistent())
return new OWLDataPropertyNodeSet(new OWLDataPropertyNode(factory.getOWLBottomDataProperty()));
else if (propertyExpression.isOWLBottomDataProperty() && isConsistent())
return new OWLDataPropertyNodeSet(new OWLDataPropertyNode(factory.getOWLTopDataProperty()));
else
return new OWLDataPropertyNodeSet();
}
}
protected boolean isDisjointDataProperty(OWLDataPropertyExpression propertyExpression1,OWLDataPropertyExpression propertyExpression2) {
checkPreConditions(propertyExpression1,propertyExpression2);
if (!m_isConsistent.booleanValue())
return true;
Role role1=H(propertyExpression1);
Role role2=H(propertyExpression2);
Individual freshIndividualA=Individual.createAnonymous("fresh-individual");
Constant freshConstant=Constant.createAnonymous("fresh-constant");
Atom roleAssertion1=role1.getRoleAssertion(freshIndividualA,freshConstant);
Atom roleAssertion2=role2.getRoleAssertion(freshIndividualA,freshConstant);
Set perTestAtoms=new HashSet<>(2);
perTestAtoms.add(roleAssertion1);
perTestAtoms.add(roleAssertion2);
return !getTableau().isSatisfiable(false,perTestAtoms,null,null,null,null,new ReasoningTaskDescription(true,"disjointness of {0} and {1}",role1,role2));
}
protected boolean isFunctional(OWLDataProperty property) {
checkPreConditions(property);
if (!m_isConsistent.booleanValue())
return true;
AtomicRole atomicRole=H(property);
Individual freshIndividual=Individual.createAnonymous("fresh-individual");
Constant freshConstantA=Constant.createAnonymous("fresh-constant-A");
Constant freshConstantB=Constant.createAnonymous("fresh-constant-B");
Set assertions=new HashSet<>();
assertions.add(atomicRole.getRoleAssertion(freshIndividual,freshConstantA));
assertions.add(atomicRole.getRoleAssertion(freshIndividual,freshConstantB));
assertions.add(Atom.create(Inequality.INSTANCE,freshConstantA,freshConstantB));
return !getTableau().isSatisfiable(false,assertions,null,null,null,null,new ReasoningTaskDescription(true,"functionality of {0}",atomicRole));
}
protected HierarchyNode getHierarchyNode(OWLDataProperty property) {
checkPreConditions(property);
classifyDataProperties();
if (!m_isConsistent.booleanValue())
return m_dataRoleHierarchy.getBottomNode();
else {
AtomicRole atomicRole=H(property);
HierarchyNode node=m_dataRoleHierarchy.getNodeForElement(atomicRole);
if (node==null)
node=new HierarchyNode<>(atomicRole,Collections.singleton(atomicRole),Collections.singleton(m_dataRoleHierarchy.getTopNode()),Collections.singleton(m_dataRoleHierarchy.getBottomNode()));
return node;
}
}
// Individual inferences
protected void realise() {
checkPreConditions();
if (!m_dlOntology.getAllIndividuals().isEmpty()) {
classifyClasses();
initialiseClassInstanceManager();
m_instanceManager.realize(m_configuration.reasonerProgressMonitor);
}
}
/**
* Realise object properties.
*/
public void realiseObjectProperties() {
checkPreConditions();
if (!m_dlOntology.getAllIndividuals().isEmpty()) {
classifyObjectProperties();
initialisePropertiesInstanceManager();
m_instanceManager.realizeObjectRoles(m_configuration.reasonerProgressMonitor);
}
}
/**
* Precompute.
*/
public void precomputeSameAsEquivalenceClasses() {
checkPreConditions();
if (!m_dlOntology.getAllIndividuals().isEmpty()) {
initialiseClassInstanceManager();
m_instanceManager.computeSameAsEquivalenceClasses(m_configuration.reasonerProgressMonitor);
}
}
@Override
public NodeSet getTypes(OWLNamedIndividual namedIndividual,boolean direct) {
checkPreConditions(namedIndividual);
Set> result;
if (!isDefined(namedIndividual)) {
classifyClasses();
result=new HashSet<>();
result.add(m_atomicConceptHierarchy.getTopNode());
}
else {
if (direct)
classifyClasses();
initialiseClassInstanceManager();
if (direct)
m_instanceManager.setToClassifiedConceptHierarchy(m_atomicConceptHierarchy);
result=m_instanceManager.getTypes(H(namedIndividual),direct);
}
return atomicConceptHierarchyNodesToNodeSet(result);
}
/**
* @param namedIndividual namedIndividual
* @param type type
* @param direct direct
* @return true if as type
*/
public boolean hasType(OWLNamedIndividual namedIndividual,OWLClassExpression type,boolean direct) {
checkPreConditions(namedIndividual,type);
if (!m_isConsistent.booleanValue())
return true;
if (!isDefined(namedIndividual))
return getEquivalentClasses(type).contains(df.getOWLThing());
else {
if (type instanceof OWLClass) {
if (direct)
classifyClasses();
initialiseClassInstanceManager();
if (direct)
m_instanceManager.setToClassifiedConceptHierarchy(m_atomicConceptHierarchy);
return m_instanceManager.hasType(H(namedIndividual),H((OWLClass)type),direct);
}
else {
OWLDataFactory factory=getDataFactory();
OWLAxiom negatedAssertionAxiom=factory.getOWLClassAssertionAxiom(type.getObjectComplementOf(),namedIndividual);
Tableau tableau=getTableau(negatedAssertionAxiom);
boolean result=tableau.isSatisfiable(true,true,null,null,null,null,null,ReasoningTaskDescription.isInstanceOf(namedIndividual,type));
tableau.clearAdditionalDLOntology();
return !result;
}
}
}
@Override
public NodeSet getInstances(OWLClassExpression classExpression,boolean direct) {
if (!m_dlOntology.getAllIndividuals().isEmpty()) {
checkPreConditions(classExpression);
if (!m_isConsistent.booleanValue()) {
Node node=new OWLNamedIndividualNode(getAllNamedIndividuals());
return new OWLNamedIndividualNodeSet(Collections.singleton(node));
}
if (direct || !(classExpression instanceof OWLClass))
classifyClasses();
initialiseClassInstanceManager();
Set result=null;
if (classExpression instanceof OWLClass)
result=m_instanceManager.getInstances(H((OWLClass)classExpression),direct);
else {
HierarchyNode hierarchyNode=getHierarchyNode(classExpression); //defines internal:query-concept as equivalent to the queried (complex) concepts and inserts internal:query-concept into the class hierarchy
result=m_instanceManager.getInstances(hierarchyNode,direct); // gets instances of classes that are direct subclasses of internal:query-concept
OWLDataFactory factory=getDataFactory();
OWLClass queryClass=factory.getOWLClass(IRI.create("internal:query-concept"));
OWLAxiom queryClassDefinition=factory.getOWLSubClassOfAxiom(queryClass,classExpression.getObjectComplementOf());
AtomicConcept queryConcept=AtomicConcept.create("internal:query-concept");
Set> visitedNodes=new HashSet<>(hierarchyNode.getChildNodes());
List> toVisit=new ArrayList<>(hierarchyNode.getParentNodes()); //look for (direct) sibling nodes
while (!toVisit.isEmpty()) {
HierarchyNode node=toVisit.remove(toVisit.size()-1);
if (visitedNodes.add(node)) {
Set realizationForNodeConcept=m_instanceManager.getInstances(node,true);
if (realizationForNodeConcept!=null) {
Tableau tableau=getTableau(queryClassDefinition);
for (Individual individual : realizationForNodeConcept)
if (isResultRelevantIndividual(individual))
if (!tableau.isSatisfiable(true,true,Collections.singleton(Atom.create(queryConcept,individual)),null,null,null,null,ReasoningTaskDescription.isInstanceOf(individual,classExpression)))
result.add(individual);
tableau.clearAdditionalDLOntology();
}
toVisit.addAll(node.getChildNodes());
}
}
}
return sortBySameAsIfNecessary(result);
}
else
return new OWLNamedIndividualNodeSet(new HashSet>());
}
/**
* @param namedIndividual1 namedIndividual1
* @param namedIndividual2 namedIndividual2
* @return true if same individual
*/
public boolean isSameIndividual(OWLNamedIndividual namedIndividual1,OWLNamedIndividual namedIndividual2) {
checkPreConditions(namedIndividual1,namedIndividual2);
if (!m_isConsistent.booleanValue())
return true;
if (m_dlOntology.getAllIndividuals().isEmpty())
return false;
else {
initialiseClassInstanceManager();
m_instanceManager.computeSameAsEquivalenceClasses(m_configuration.reasonerProgressMonitor);
return m_instanceManager.isSameIndividual(H(namedIndividual1),H(namedIndividual2));
}
}
@Override
public Node getSameIndividuals(OWLNamedIndividual namedIndividual) {
checkPreConditions(namedIndividual);
if (!m_isConsistent.booleanValue())
return new OWLNamedIndividualNode(getAllNamedIndividuals());
if (m_dlOntology.getAllIndividuals().isEmpty() || !m_dlOntology.containsIndividual(H(namedIndividual)))
return new OWLNamedIndividualNode(namedIndividual);
else {
initialiseClassInstanceManager();
Set sameIndividuals=m_instanceManager.getSameAsIndividuals(H(namedIndividual));
OWLDataFactory factory=getDataFactory();
Set result=new HashSet<>();
for (Individual individual : sameIndividuals)
result.add(factory.getOWLNamedIndividual(IRI.create(individual.getIRI())));
return new OWLNamedIndividualNode(result);
}
}
@Override
public NodeSet getDifferentIndividuals(OWLNamedIndividual namedIndividual) {
checkPreConditions(namedIndividual);
if (!m_isConsistent.booleanValue()) {
Node node=new OWLNamedIndividualNode(getAllNamedIndividuals());
return new OWLNamedIndividualNodeSet(Collections.singleton(node));
}
Individual individual=H(namedIndividual);
Tableau tableau=getTableau();
Set result=new HashSet<>();
for (Individual potentiallyDifferentIndividual : m_dlOntology.getAllIndividuals())
if (isResultRelevantIndividual(potentiallyDifferentIndividual) && !individual.equals(potentiallyDifferentIndividual))
if (!tableau.isSatisfiable(true,true,Collections.singleton(Atom.create(Equality.INSTANCE,individual,potentiallyDifferentIndividual)),null,null,null,null,new ReasoningTaskDescription(true,"is {0} different from {1}",individual,potentiallyDifferentIndividual)))
result.add(potentiallyDifferentIndividual);
return sortBySameAsIfNecessary(result);
}
@Override
public NodeSet getObjectPropertyValues(OWLNamedIndividual namedIndividual,OWLObjectPropertyExpression propertyExpression) {
checkPreConditions(namedIndividual,propertyExpression);
if (!m_isConsistent.booleanValue()) {
Node node=new OWLNamedIndividualNode(getAllNamedIndividuals());
return new OWLNamedIndividualNodeSet(Collections.singleton(node));
}
AtomicRole role=H(propertyExpression.getNamedProperty());
if (!m_dlOntology.containsObjectRole(role))
return new OWLNamedIndividualNodeSet();
initialisePropertiesInstanceManager();
Individual individual=H(namedIndividual);
Set result;
if (propertyExpression.isAnonymous()) {
// inverse role
result=m_instanceManager.getObjectPropertySubjects(role,individual);
} else {
// named role
result=m_instanceManager.getObjectPropertyValues(role,individual);
}
return sortBySameAsIfNecessary(result);
}
/**
* @param property property
* @return object property instances
*/
public Map> getObjectPropertyInstances(OWLObjectProperty property) {
checkPreConditions(property);
Map> result=new HashMap<>();
if (!m_isConsistent.booleanValue()) {
Set all=getAllNamedIndividuals();
for (OWLNamedIndividual ind : all)
result.put(ind,all);
return result;
}
initialisePropertiesInstanceManager();
AtomicRole role=H(property);
Map> relations=m_instanceManager.getObjectPropertyInstances(role);
OWLDataFactory factory=getDataFactory();
relations.forEach((individual, set)->{
Set successors=new HashSet<>();
result.put(factory.getOWLNamedIndividual(IRI.create(individual.getIRI())),successors);
for (Individual successorIndividual : set)
successors.add(factory.getOWLNamedIndividual(IRI.create(successorIndividual.getIRI())));
});
return result;
}
/**
* @param _subject subject
* @param propertyExpression propertyExpression
* @param _object object
* @return true if has object property relationships
*/
public boolean hasObjectPropertyRelationship(OWLNamedIndividual _subject,OWLObjectPropertyExpression propertyExpression,OWLNamedIndividual _object) {
OWLNamedIndividual subject=_subject;
OWLNamedIndividual object=_object;
checkPreConditions(subject,propertyExpression,object);
if (!m_isConsistent.booleanValue())
return true;
initialisePropertiesInstanceManager();
OWLObjectProperty property=propertyExpression.getNamedProperty();
if (propertyExpression.isAnonymous()) {
OWLNamedIndividual tmp=subject;
subject=object;
object=tmp;
}
AtomicRole role=H(property);
Individual subj=H(subject);
Individual obj=H(object);
return m_instanceManager.hasObjectRoleRelationship(role,subj,obj);
}
@Override
public Set getDataPropertyValues(OWLNamedIndividual namedIndividual,OWLDataProperty property) {
checkPreConditions(namedIndividual,property);
Set result=new HashSet<>();
if (m_dlOntology.hasDatatypes()) {
OWLDataFactory factory=getDataFactory();
Set relevantDataProperties=asSet(getSubDataProperties(property,false).entities());
relevantDataProperties.add(property);
List relevantIndividuals=asList(getSameIndividuals(namedIndividual).entities());
for (OWLDataProperty dataProperty : relevantDataProperties) {
if (!dataProperty.isBottomEntity()) {
AtomicRole atomicRole=H(dataProperty);
Map> dataPropertyAssertions=m_dlOntology.getDataPropertyAssertions().get(atomicRole);
if (dataPropertyAssertions!=null) {
for (OWLNamedIndividual ind : relevantIndividuals) {
Individual individual=H(ind);
if (dataPropertyAssertions.containsKey(individual)) {
for (Constant constant : dataPropertyAssertions.get(individual)) {
String lexicalForm=constant.getLexicalForm();
String datatypeURI=constant.getDatatypeURI();
OWLLiteral literal;
if ((Prefixes.s_semanticWebPrefixes.get("rdf:")+"PlainLiteral").equals(datatypeURI)) {
int atPosition=lexicalForm.lastIndexOf('@');
literal=factory.getOWLLiteral(lexicalForm.substring(0,atPosition),lexicalForm.substring(atPosition+1));
}
else
literal=factory.getOWLLiteral(lexicalForm,factory.getOWLDatatype(IRI.create(datatypeURI)));
result.add(literal);
}
}
}
}
}
}
}
return result;
}
/**
* @param subject subject
* @param property property
* @param object object
* @return true if relationship exists
*/
public boolean hasDataPropertyRelationship(OWLNamedIndividual subject,OWLDataProperty property,OWLLiteral object) {
checkPreConditions(subject,property);
if (!m_isConsistent.booleanValue())
return true;
OWLDataFactory factory=getDataFactory();
OWLAxiom notAssertion=factory.getOWLNegativeDataPropertyAssertionAxiom(property,subject,object);
Tableau tableau=getTableau(notAssertion);
boolean result=tableau.isSatisfiable(true,true,null,null,null,null,null,new ReasoningTaskDescription(true,"is {0} connected to {1} via {2}",H(subject),object,H(property)));
tableau.clearAdditionalDLOntology();
return !result;
}
protected Set> getDirectSuperConceptNodes(final Individual individual) {
HierarchySearch.SearchPredicate> predicate=new HierarchySearch.SearchPredicate>() {
@Override
public Set> getSuccessorElements(HierarchyNode u) {
return u.getChildNodes();
}
@Override
public Set> getPredecessorElements(HierarchyNode u) {
return u.getParentNodes();
}
@Override
public boolean trueOf(HierarchyNode u) {
AtomicConcept atomicConcept=u.getRepresentative();
if (AtomicConcept.THING.equals(atomicConcept))
return true;
else
return !getTableau().isSatisfiable(true,true,null,Collections.singleton(Atom.create(atomicConcept,individual)),null,null,null,ReasoningTaskDescription.isInstanceOf(atomicConcept,individual));
}
};
return HierarchySearch.search(predicate,Collections.singleton(m_atomicConceptHierarchy.getTopNode()),null);
}
protected NodeSet sortBySameAsIfNecessary(Set individuals) {
OWLDataFactory factory=getDataFactory();
Set> result=new HashSet<>();
if (m_configuration.individualNodeSetPolicy==IndividualNodeSetPolicy.BY_SAME_AS) {
// group the individuals by same as equivalence classes
while (!individuals.isEmpty()) {
initialiseClassInstanceManager();
Individual individual=individuals.iterator().next();
Set sameIndividuals=m_instanceManager.getSameAsIndividuals(individual);
Set sameNamedIndividuals=new HashSet<>();
for (Individual sameIndividual : sameIndividuals)
sameNamedIndividuals.add(factory.getOWLNamedIndividual(IRI.create(sameIndividual.getIRI())));
individuals.removeAll(sameIndividuals);
result.add(new OWLNamedIndividualNode(sameNamedIndividuals));
}
}
else {
for (Individual individual : individuals)
result.add(new OWLNamedIndividualNode(factory.getOWLNamedIndividual(IRI.create(individual.getIRI()))));
}
return new OWLNamedIndividualNodeSet(result);
}
protected Set getAllNamedIndividuals() {
Set result=new HashSet<>();
OWLDataFactory factory=getDataFactory();
for (Individual individual : m_dlOntology.getAllIndividuals())
if (isResultRelevantIndividual(individual))
result.add(factory.getOWLNamedIndividual(IRI.create(individual.getIRI())));
return result;
}
protected static boolean isResultRelevantIndividual(Individual individual) {
return !individual.isAnonymous() && !Prefixes.isInternalIRI(individual.getIRI());
}
// Various creation methods
/**
* @return tableau
*/
public Tableau getTableau() {
m_tableau.clearAdditionalDLOntology();
return m_tableau;
}
/**
* A mostly internal method. Can be used to retrieve a tableau for axioms in the given ontology manager plus an additional set of axioms.
*
* @param additionalAxioms
* - a list of additional axioms that should be included in the tableau
* @return a tableau containing rules for the normalised axioms, this tableau is not permanent in the reasoner, i.e., it does not overwrite the originally created tableau
* @throws IllegalArgumentException
* - if the axioms lead to non-admissible clauses, some configuration parameters are incompatible or other such errors
*/
public Tableau getTableau(OWLAxiom... additionalAxioms) throws IllegalArgumentException {
if (additionalAxioms==null || additionalAxioms.length==0)
return getTableau();
else {
DLOntology deltaDLOntology=createDeltaDLOntology(m_configuration,m_dlOntology,additionalAxioms);
if (m_tableau.supportsAdditionalDLOntology(deltaDLOntology)) {
m_tableau.setAdditionalDLOntology(deltaDLOntology);
return m_tableau;
}
else
return createTableau(m_interruptFlag,m_configuration,m_dlOntology,deltaDLOntology,m_prefixes);
}
}
protected static Tableau createTableau(InterruptFlag interruptFlag,Configuration configuration,DLOntology permanentDLOntology,DLOntology additionalDLOntology,Prefixes prefixes) throws IllegalArgumentException {
boolean hasInverseRoles=(permanentDLOntology.hasInverseRoles() || (additionalDLOntology!=null && additionalDLOntology.hasInverseRoles()));
boolean hasNominals=(permanentDLOntology.hasNominals() || (additionalDLOntology!=null && additionalDLOntology.hasNominals()));
TableauMonitor wellKnownTableauMonitor=null;
switch (configuration.tableauMonitorType) {
case NONE:
break;
case TIMING:
wellKnownTableauMonitor=new Timer(System.out);
break;
case TIMING_WITH_PAUSE:
wellKnownTableauMonitor=new TimerWithPause(System.out);
break;
case DEBUGGER_HISTORY_ON:
wellKnownTableauMonitor=new Debugger(prefixes,true);
break;
case DEBUGGER_NO_HISTORY:
wellKnownTableauMonitor=new Debugger(prefixes,false);
break;
default:
throw new IllegalArgumentException("Unknown monitor type");
}
TableauMonitor tableauMonitor=null;
if (configuration.monitor==null)
tableauMonitor=wellKnownTableauMonitor;
else if (wellKnownTableauMonitor==null)
tableauMonitor=configuration.monitor;
else
tableauMonitor=new TableauMonitorFork(wellKnownTableauMonitor,configuration.monitor);
DirectBlockingChecker directBlockingChecker=null;
switch (configuration.directBlockingType) {
case OPTIMAL:
if (configuration.blockingStrategyType==BlockingStrategyType.SIMPLE_CORE || configuration.blockingStrategyType==BlockingStrategyType.COMPLEX_CORE)
directBlockingChecker=new ValidatedSingleDirectBlockingChecker(hasInverseRoles);
else if (hasInverseRoles)
directBlockingChecker=new PairWiseDirectBlockingChecker();
else
directBlockingChecker=new SingleDirectBlockingChecker();
break;
case SINGLE:
if (configuration.blockingStrategyType==BlockingStrategyType.SIMPLE_CORE || configuration.blockingStrategyType==BlockingStrategyType.COMPLEX_CORE)
directBlockingChecker=new ValidatedSingleDirectBlockingChecker(hasInverseRoles);
else
directBlockingChecker=new SingleDirectBlockingChecker();
break;
case PAIR_WISE:
if (configuration.blockingStrategyType==BlockingStrategyType.SIMPLE_CORE || configuration.blockingStrategyType==BlockingStrategyType.COMPLEX_CORE)
directBlockingChecker=new ValidatedPairwiseDirectBlockingChecker(hasInverseRoles);
else
directBlockingChecker=new PairWiseDirectBlockingChecker();
break;
default:
throw new IllegalArgumentException("Unknown direct blocking type.");
}
BlockingSignatureCache blockingSignatureCache=null;
if (!hasNominals && !(configuration.blockingStrategyType==BlockingStrategyType.SIMPLE_CORE || configuration.blockingStrategyType==BlockingStrategyType.COMPLEX_CORE)) {
switch (configuration.blockingSignatureCacheType) {
case CACHED:
blockingSignatureCache=new BlockingSignatureCache(directBlockingChecker);
break;
case NOT_CACHED:
break;
default:
throw new IllegalArgumentException("Unknown blocking cache type.");
}
}
BlockingStrategy blockingStrategy=null;
switch (configuration.blockingStrategyType) {
case ANCESTOR:
blockingStrategy=new AncestorBlocking(directBlockingChecker,blockingSignatureCache);
break;
case ANYWHERE:
blockingStrategy=new AnywhereBlocking(directBlockingChecker,blockingSignatureCache);
break;
case SIMPLE_CORE:
blockingStrategy=new AnywhereValidatedBlocking(directBlockingChecker,true);
break;
case COMPLEX_CORE:
blockingStrategy=new AnywhereValidatedBlocking(directBlockingChecker,false);
break;
case OPTIMAL:
blockingStrategy=new AnywhereBlocking(directBlockingChecker,blockingSignatureCache);
break;
default:
throw new IllegalArgumentException("Unknown blocking strategy type.");
}
ExistentialExpansionStrategy existentialsExpansionStrategy=null;
switch (configuration.existentialStrategyType) {
case CREATION_ORDER:
existentialsExpansionStrategy=new CreationOrderStrategy(blockingStrategy);
break;
case EL:
existentialsExpansionStrategy=new IndividualReuseStrategy(blockingStrategy,true);
break;
case INDIVIDUAL_REUSE:
existentialsExpansionStrategy=new IndividualReuseStrategy(blockingStrategy,false);
break;
default:
throw new IllegalArgumentException("Unknown expansion strategy type.");
}
return new Tableau(interruptFlag,tableauMonitor,existentialsExpansionStrategy,configuration.useDisjunctionLearning,permanentDLOntology,additionalDLOntology,configuration.parameters);
}
protected Hierarchy classifyAtomicConcepts(Tableau tableau,ClassificationProgressMonitor progressMonitor,AtomicConcept topElement,AtomicConcept bottomElement,Set elements,boolean forceQuasiOrder) {
if (tableau.isDeterministic() && !forceQuasiOrder)
return new DeterministicClassification(tableau,progressMonitor,topElement,bottomElement,elements).classify();
else
return new QuasiOrderClassification(tableau,progressMonitor,topElement,bottomElement,elements).classify();
}
protected Hierarchy classifyAtomicConceptsForRoles(Tableau tableau,ClassificationProgressMonitor progressMonitor,AtomicConcept topElement,AtomicConcept bottomElement,Set elements,boolean hasInverses,Map conceptsForRoles,Map rolesForConcepts,boolean forceQuasiOrder) {
if (tableau.isDeterministic() && !forceQuasiOrder)
return new DeterministicClassification(tableau,progressMonitor,topElement,bottomElement,elements).classify();
else
return new QuasiOrderClassificationForRoles(tableau,progressMonitor,topElement,bottomElement,elements,hasInverses,conceptsForRoles,rolesForConcepts).classify();
}
protected DLOntology createDeltaDLOntology(Configuration configuration,DLOntology originalDLOntology,OWLAxiom... additionalAxioms) throws IllegalArgumentException {
Set additionalAxiomsSet=new HashSet<>();
for (OWLAxiom axiom : additionalAxioms) {
if (isUnsupportedExtensionAxiom(axiom))
throw new IllegalArgumentException("Internal error: unsupported extension axiom type.");
additionalAxiomsSet.add(axiom);
}
OWLDataFactory dataFactory=getDataFactory();
OWLAxioms axioms=new OWLAxioms();
axioms.m_definedDatatypesIRIs.addAll(originalDLOntology.getDefinedDatatypeIRIs());
OWLNormalization normalization=new OWLNormalization(dataFactory,axioms,originalDLOntology.getAllAtomicConcepts().size());
normalization.processAxioms(additionalAxiomsSet.stream());
BuiltInPropertyManager builtInPropertyManager=new BuiltInPropertyManager(dataFactory);
builtInPropertyManager.axiomatizeBuiltInPropertiesAsNeeded(axioms,originalDLOntology.getAllAtomicObjectRoles().contains(AtomicRole.TOP_OBJECT_ROLE),originalDLOntology.getAllAtomicObjectRoles().contains(AtomicRole.BOTTOM_OBJECT_ROLE),originalDLOntology.getAllAtomicObjectRoles().contains(AtomicRole.TOP_DATA_ROLE),originalDLOntology.getAllAtomicObjectRoles().contains(AtomicRole.BOTTOM_DATA_ROLE));
int currentReplacementIndex=m_objectPropertyInclusionManager.rewriteNegativeObjectPropertyAssertions(dataFactory,axioms,originalDLOntology.getAllAtomicConcepts().size());
m_objectPropertyInclusionManager.rewriteAxioms(dataFactory,axioms,currentReplacementIndex);
OWLAxiomsExpressivity axiomsExpressivity=new OWLAxiomsExpressivity(axioms);
axiomsExpressivity.m_hasAtMostRestrictions|=originalDLOntology.hasAtMostRestrictions();
axiomsExpressivity.m_hasInverseRoles|=originalDLOntology.hasInverseRoles();
axiomsExpressivity.m_hasNominals|=originalDLOntology.hasNominals();
axiomsExpressivity.m_hasDatatypes|=originalDLOntology.hasDatatypes();
OWLClausification clausifier=new OWLClausification(configuration);
Set descriptionGraphs=Collections.emptySet();
return clausifier.clausify(dataFactory,"uri:urn:internal-kb",axioms,axiomsExpressivity,descriptionGraphs);
}
protected static boolean isUnsupportedExtensionAxiom(OWLAxiom axiom) {
return
axiom instanceof OWLSubObjectPropertyOfAxiom ||
axiom instanceof OWLTransitiveObjectPropertyAxiom ||
axiom instanceof OWLSubPropertyChainOfAxiom ||
axiom instanceof OWLFunctionalObjectPropertyAxiom ||
axiom instanceof OWLInverseFunctionalObjectPropertyAxiom ||
axiom instanceof SWRLRule;
}
// Hierarchy printing
/**
* Writes out the hierarchies quickly
*
* @param out
* - the printwriter that is used to output the hierarchies
* @param classes
* - if true, the class hierarchy is printed
* @param objectProperties
* - if true, the object property hierarchy is printed
* @param dataProperties
* - if true, the data property hierarchy is printed
*/
public void dumpHierarchies(PrintWriter out,boolean classes,boolean objectProperties,boolean dataProperties) {
HierarchyDumperFSS printer=new HierarchyDumperFSS(out);
if (classes) {
classifyClasses();
printer.printAtomicConceptHierarchy(m_atomicConceptHierarchy);
}
if (objectProperties) {
classifyObjectProperties();
printer.printObjectPropertyHierarchy(m_objectRoleHierarchy);
}
if (dataProperties) {
classifyDataProperties();
printer.printDataPropertyHierarchy(m_dataRoleHierarchy);
}
}
/**
* Prints the hierarchies into a functional style syntax ontology all nicely sorted alphabetically.
*
* @param out
* - the printwriter that is used to output the hierarchies
* @param classes
* - if true, the class hierarchy is printed
* @param objectProperties
* - if true, the object property hierarchy is printed
* @param dataProperties
* - if true, the data property hierarchy is printed
*/
public void printHierarchies(PrintWriter out,boolean classes,boolean objectProperties,boolean dataProperties) {
HierarchyPrinterFSS printer=new HierarchyPrinterFSS(out,m_dlOntology.getOntologyIRI()+"#");
if (classes) {
classifyClasses();
printer.loadAtomicConceptPrefixIRIs(m_atomicConceptHierarchy.getAllElements());
}
if (objectProperties) {
classifyObjectProperties();
printer.loadAtomicRolePrefixIRIs(m_dlOntology.getAllAtomicObjectRoles());
}
if (dataProperties) {
classifyDataProperties();
printer.loadAtomicRolePrefixIRIs(m_dlOntology.getAllAtomicDataRoles());
}
printer.startPrinting();
boolean atLF=true;
if (classes && !m_atomicConceptHierarchy.isEmpty()) {
printer.printAtomicConceptHierarchy(m_atomicConceptHierarchy);
atLF=false;
}
if (objectProperties && !m_objectRoleHierarchy.isEmpty()) {
if (!atLF)
out.println();
printer.printRoleHierarchy(m_objectRoleHierarchy,true);
atLF=false;
}
if (dataProperties && !m_dataRoleHierarchy.isEmpty()) {
if (!atLF)
out.println();
printer.printRoleHierarchy(m_dataRoleHierarchy,false);
atLF=false;
}
printer.endPrinting();
}
// Various utility methods
protected void checkPreConditions(OWLObject... objects) {
flushChangesIfRequired();
if (objects!=null && objects.length>0)
throwFreshEntityExceptionIfNecessary(objects);
throwInconsistentOntologyExceptionIfNecessary();
}
protected void flushChangesIfRequired() {
if (!m_configuration.bufferChanges && !m_pendingChanges.isEmpty())
flush();
}
protected void throwInconsistentOntologyExceptionIfNecessary() {
if (!isConsistent() && m_configuration.throwInconsistentOntologyException)
throw new InconsistentOntologyException();
}
protected void throwFreshEntityExceptionIfNecessary(OWLObject... objects) {
if (m_configuration.freshEntityPolicy==FreshEntityPolicy.DISALLOW) {
Set undeclaredEntities=new HashSet<>();
for (OWLObject object : objects) {
if (!(object instanceof OWLEntity) || !((OWLEntity)object).isBuiltIn()) {
object.dataPropertiesInSignature()
.filter(dp->!isDefined(dp) && notInternal(dp))
.forEach(undeclaredEntities::add);
object.objectPropertiesInSignature()
.filter(op->!isDefined(op) && notInternal(op))
.forEach(undeclaredEntities::add);
object.individualsInSignature()
.filter(i->!isDefined(i) && notInternal(i))
.forEach(undeclaredEntities::add);
object.classesInSignature()
.filter(c->!isDefined(c) && notInternal(c))
.forEach(undeclaredEntities::add);
}
}
if (!undeclaredEntities.isEmpty())
throw new FreshEntitiesException(undeclaredEntities);
}
}
protected boolean notInternal(OWLEntity dp) {
return !Prefixes.isInternalIRI(dp.getIRI().toString());
}
protected boolean containsFreshEntities(OWLObject... objects) {
for (OWLObject object : objects) {
if (!(object instanceof OWLEntity) || !((OWLEntity)object).isBuiltIn()) {
if (object.dataPropertiesInSignature()
.anyMatch(dp->!isDefined(dp) && notInternal(dp)))
return true;
if (object.objectPropertiesInSignature()
.anyMatch(op->!isDefined(op) && notInternal(op)))
return true;
if (object.individualsInSignature()
.anyMatch(i->!isDefined(i) && notInternal(i)))
return true;
if (object.classesInSignature()
.anyMatch(c->!isDefined(c) && notInternal(c)))
return true;
}
}
return false;
}
// Methods for conversion from OWL API to HermiT's API
protected static AtomicConcept H(OWLClass owlClass) {
return AtomicConcept.create(owlClass.getIRI().toString());
}
protected static AtomicRole H(OWLObjectProperty objectProperty) {
return AtomicRole.create(objectProperty.getIRI().toString());
}
protected static Role H(OWLObjectPropertyExpression objectPropertyExpression) {
if (objectPropertyExpression instanceof OWLObjectProperty)
return H((OWLObjectProperty)objectPropertyExpression);
else
return H(objectPropertyExpression.getNamedProperty()).getInverse();
}
protected static AtomicRole H(OWLDataProperty dataProperty) {
return AtomicRole.create(dataProperty.getIRI().toString());
}
protected static Role H(OWLDataPropertyExpression dataPropertyExpression) {
return H((OWLDataProperty)dataPropertyExpression);
}
protected static Individual H(OWLNamedIndividual namedIndividual) {
return Individual.create(namedIndividual.getIRI().toString());
}
protected static Individual H(OWLAnonymousIndividual anonymousIndividual) {
return Individual.createAnonymous(anonymousIndividual.getID().toString());
}
protected static Individual H(OWLIndividual individual) {
if (individual.isAnonymous())
return H((OWLAnonymousIndividual)individual);
else
return H((OWLNamedIndividual)individual);
}
// Extended methods for conversion from HermiT's API to OWL API
protected Node atomicConceptHierarchyNodeToNode(HierarchyNode hierarchyNode) {
Set result=new HashSet<>();
OWLDataFactory factory=getDataFactory();
for (AtomicConcept concept : hierarchyNode.getEquivalentElements())
if (!Prefixes.isInternalIRI(concept.getIRI()))
result.add(factory.getOWLClass(IRI.create(concept.getIRI())));
return new OWLClassNode(result);
}
protected NodeSet atomicConceptHierarchyNodesToNodeSet(Collection> hierarchyNodes) {
Set> result=new HashSet<>();
for (HierarchyNode hierarchyNode : hierarchyNodes) {
Node node=atomicConceptHierarchyNodeToNode(hierarchyNode);
if (node.getSize()!=0)
result.add(node);
}
return new OWLClassNodeSet(result);
}
protected Node objectPropertyHierarchyNodeToNode(HierarchyNode hierarchyNode) {
Set result=new HashSet<>();
OWLDataFactory factory=getDataFactory();
for (Role role : hierarchyNode.getEquivalentElements()) {
if (role instanceof AtomicRole)
result.add(factory.getOWLObjectProperty(IRI.create(((AtomicRole)role).getIRI())));
else {
OWLObjectProperty ope=factory.getOWLObjectProperty(IRI.create(((InverseRole)role).getInverseOf().getIRI()));
result.add(factory.getOWLObjectInverseOf(ope));
}
}
return new OWLObjectPropertyNode(result);
}
protected NodeSet objectPropertyHierarchyNodesToNodeSet(Collection> hierarchyNodes) {
Set> result=new HashSet<>();
for (HierarchyNode hierarchyNode : hierarchyNodes) {
result.add(objectPropertyHierarchyNodeToNode(hierarchyNode));
}
return new OWLObjectPropertyNodeSet(result);
}
protected Node dataPropertyHierarchyNodeToNode(HierarchyNode hierarchyNode) {
Set result=new HashSet<>();
OWLDataFactory factory=getDataFactory();
for (AtomicRole atomicRole : hierarchyNode.getEquivalentElements())
result.add(factory.getOWLDataProperty(IRI.create(atomicRole.getIRI())));
return new OWLDataPropertyNode(result);
}
protected NodeSet dataPropertyHierarchyNodesToNodeSet(Collection> hierarchyNodes) {
Set> result=new HashSet<>();
for (HierarchyNode hierarchyNode : hierarchyNodes)
result.add(dataPropertyHierarchyNodeToNode(hierarchyNode));
return new OWLDataPropertyNodeSet(result);
}
// The factory for OWL API reasoners
/**
* Compatibility class: extends org.semanticweb.HermiT.ReasonerFactory so exisitng clients do not have to change.
* Problem with inner factory is that it cannot be used easily through reflection.
* @deprecated use org.semanticweb.HermiT.ReasonerFactory
*/@Deprecated
public static class ReasonerFactory extends org.semanticweb.HermiT.ReasonerFactory {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy