/* 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 <http://www.gnu.org/licenses/>.
*/
package org.semanticweb.HermiT.hierarchy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import org.semanticweb.HermiT.Prefixes;
import org.semanticweb.HermiT.Reasoner;
import org.semanticweb.HermiT.graph.Graph;
import org.semanticweb.HermiT.hierarchy.DeterministicClassification.GraphNode;
import org.semanticweb.HermiT.hierarchy.RoleElementManager.RoleElement;
import org.semanticweb.HermiT.model.Atom;
import org.semanticweb.HermiT.model.AtomicConcept;
import org.semanticweb.HermiT.model.AtomicRole;
import org.semanticweb.HermiT.model.DLClause;
import org.semanticweb.HermiT.model.DLOntology;
import org.semanticweb.HermiT.model.DLPredicate;
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.tableau.ExtensionManager;
import org.semanticweb.HermiT.tableau.ExtensionTable;
import org.semanticweb.HermiT.tableau.InterruptFlag;
import org.semanticweb.HermiT.tableau.Node;
import org.semanticweb.HermiT.tableau.NodeType;
import org.semanticweb.HermiT.tableau.ReasoningTaskDescription;
import org.semanticweb.HermiT.tableau.Tableau;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.reasoner.ReasonerProgressMonitor;
public class InstanceManager {
public static final int thresholdForAdditionalAxioms=10000;
protected final InterruptFlag m_interruptFlag;
protected final Reasoner m_reasoner;
protected final TableauMonitor m_tableauMonitor;
protected final Individual[] m_individuals;
protected final HashSet<AtomicRole> m_complexRoles;
protected final Map<AtomicConcept,AtomicConceptElement> m_conceptToElement;
protected final AtomicConcept m_topConcept;
protected final AtomicConcept m_bottomConcept;
protected Hierarchy<AtomicConcept> m_currentConceptHierarchy;
protected final RoleElementManager m_roleElementManager;
protected final RoleElement m_topRoleElement;
protected final RoleElement m_bottomRoleElement;
protected Hierarchy<RoleElement> m_currentRoleHierarchy;
protected final boolean m_usesInverseRoles;
protected final Map<Individual, Node> m_nodesForIndividuals;
protected final Map<Node,Individual> m_individualsForNodes;
protected final Map<Node,Set<Node>> m_canonicalNodeToDetMergedNodes;
protected final Map<Node,Set<Node>> m_canonicalNodeToNonDetMergedNodes;
protected boolean m_isInconsistent;
protected boolean m_realizationCompleted;
protected boolean m_roleRealizationCompleted;
protected boolean m_usesClassifiedConceptHierarchy;
protected boolean m_usesClassifiedObjectRoleHierarchy;
protected boolean m_classesInitialised;
protected boolean m_propertiesInitialised;
protected boolean m_readingOffFoundPossibleConceptInstance;
protected boolean m_readingOffFoundPossiblePropertyInstance;
protected final Map<Individual,Set<Individual>> m_individualToEquivalenceClass;
protected Map<Set<Individual>,Set<Set<Individual>>> m_individualToPossibleEquivalenceClass;
protected final ExtensionTable.Retrieval m_binaryRetrieval0Bound;
protected final ExtensionTable.Retrieval m_binaryRetrieval1Bound;
protected final ExtensionTable.Retrieval m_binaryRetrieval01Bound;
protected final ExtensionTable.Retrieval m_ternaryRetrieval1Bound;
protected final ExtensionTable.Retrieval m_ternaryRetrieval0Bound;
protected final ExtensionTable.Retrieval m_ternaryRetrieval012Bound;
protected int m_currentIndividualIndex=0;
public InstanceManager(InterruptFlag interruptFlag,Reasoner reasoner,Hierarchy<AtomicConcept> atomicConceptHierarchy,Hierarchy<Role> objectRoleHierarchy) {
m_interruptFlag=interruptFlag;
m_interruptFlag.startTask();
try {
m_reasoner=reasoner;
m_tableauMonitor=m_reasoner.getTableau().getTableauMonitor();
DLOntology dlo=m_reasoner.getDLOntology();
m_individuals=new ArrayList<Individual>(dlo.getAllIndividuals()).toArray(new Individual[0]);
m_complexRoles=new HashSet<AtomicRole>();
m_individualToEquivalenceClass=new HashMap<Individual, Set<Individual>>();
m_nodesForIndividuals=new HashMap<Individual,Node>();
for (Individual individual : m_individuals) {
m_nodesForIndividuals.put(individual,null);
Set<Individual> equivalentIndividuals=new HashSet<Individual>();
equivalentIndividuals.add(individual);
m_individualToEquivalenceClass.put(individual, equivalentIndividuals);
m_interruptFlag.checkInterrupt();
}
m_individualsForNodes=new HashMap<Node,Individual>();
m_canonicalNodeToDetMergedNodes=new HashMap<Node,Set<Node>>();
m_canonicalNodeToNonDetMergedNodes=new HashMap<Node,Set<Node>>();
m_individualToPossibleEquivalenceClass=null;
m_topConcept=AtomicConcept.THING;
m_bottomConcept=AtomicConcept.NOTHING;
m_conceptToElement=new HashMap<AtomicConcept, AtomicConceptElement>();
m_conceptToElement.put(m_topConcept, new AtomicConceptElement(null, null));
Graph<AtomicConcept> knownConceptSubsumptions=null;
Set<AtomicConcept> atomicConcepts=null;
if (atomicConceptHierarchy!=null)
setToClassifiedConceptHierarchy(atomicConceptHierarchy);
else {
knownConceptSubsumptions=new Graph<AtomicConcept>();
atomicConcepts=new HashSet<AtomicConcept>();
atomicConcepts.add(m_topConcept);
atomicConcepts.add(m_bottomConcept);
for (AtomicConcept atomicConcept : dlo.getAllAtomicConcepts()) {
if (!Prefixes.isInternalIRI(atomicConcept.getIRI())) {
atomicConcepts.add(atomicConcept);
addKnownConceptSubsumption(knownConceptSubsumptions,atomicConcept,atomicConcept);
addKnownConceptSubsumption(knownConceptSubsumptions,atomicConcept,m_topConcept);
addKnownConceptSubsumption(knownConceptSubsumptions,m_bottomConcept,atomicConcept);
}
m_interruptFlag.checkInterrupt();
}
addKnownConceptSubsumption(knownConceptSubsumptions,m_bottomConcept,m_bottomConcept);
}
m_roleElementManager=new RoleElementManager();
Graph<Role> knownRoleSubsumptions=null;
m_topRoleElement=m_roleElementManager.getRoleElement(AtomicRole.TOP_OBJECT_ROLE);
m_bottomRoleElement=m_roleElementManager.getRoleElement(AtomicRole.BOTTOM_OBJECT_ROLE);
m_usesInverseRoles=dlo.hasInverseRoles();
Set<Role> roles=null;
Set<Role> complexRoles=dlo.getAllComplexObjectRoles();
if (objectRoleHierarchy!=null) {
setToClassifiedRoleHierarchy(objectRoleHierarchy);
for (Role role : complexRoles)
if (role instanceof AtomicRole && role!=AtomicRole.TOP_OBJECT_ROLE && role!=AtomicRole.BOTTOM_OBJECT_ROLE)
m_complexRoles.add((AtomicRole)role);
}
else {
knownRoleSubsumptions=new Graph<Role>();
roles=new HashSet<Role>();
roles.add(AtomicRole.TOP_OBJECT_ROLE);
roles.add(AtomicRole.BOTTOM_OBJECT_ROLE);
roles.addAll(dlo.getAllAtomicObjectRoles());
for (Role role : roles) {
addKnownRoleSubsumption(knownRoleSubsumptions,role,role);
addKnownRoleSubsumption(knownRoleSubsumptions,role,AtomicRole.TOP_OBJECT_ROLE);
addKnownRoleSubsumption(knownRoleSubsumptions,AtomicRole.BOTTOM_OBJECT_ROLE,role);
if (complexRoles.contains(role) && role instanceof AtomicRole && role!=AtomicRole.TOP_OBJECT_ROLE && role!=AtomicRole.BOTTOM_OBJECT_ROLE)
m_complexRoles.add((AtomicRole)role);
m_interruptFlag.checkInterrupt();
}
addKnownRoleSubsumption(knownRoleSubsumptions,AtomicRole.BOTTOM_OBJECT_ROLE,AtomicRole.BOTTOM_OBJECT_ROLE);
}
if (atomicConceptHierarchy==null || objectRoleHierarchy==null) {
updateKnownSubsumptionsUsingToldSubsumers(dlo.getDLClauses(),knownConceptSubsumptions,atomicConcepts,knownRoleSubsumptions,roles);
}
if (atomicConceptHierarchy==null)
m_currentConceptHierarchy=buildTransitivelyReducedConceptHierarchy(knownConceptSubsumptions);
if (objectRoleHierarchy==null)
m_currentRoleHierarchy=buildTransitivelyReducedRoleHierarchy(knownRoleSubsumptions);
ExtensionManager extensionManager=m_reasoner.getTableau().getExtensionManager();
m_binaryRetrieval0Bound=extensionManager.getBinaryExtensionTable().createRetrieval(new boolean[] { true, false }, ExtensionTable.View.TOTAL);
m_binaryRetrieval1Bound=extensionManager.getBinaryExtensionTable().createRetrieval(new boolean[] { false, true }, ExtensionTable.View.TOTAL);
m_binaryRetrieval01Bound=extensionManager.getBinaryExtensionTable().createRetrieval(new boolean[] { true, true }, ExtensionTable.View.TOTAL);
m_ternaryRetrieval1Bound=extensionManager.getTernaryExtensionTable().createRetrieval(new boolean[] { false,true,false }, ExtensionTable.View.TOTAL);
m_ternaryRetrieval0Bound=extensionManager.getTernaryExtensionTable().createRetrieval(new boolean[] { true,false,false }, ExtensionTable.View.TOTAL);
m_ternaryRetrieval012Bound=extensionManager.getTernaryExtensionTable().createRetrieval(new boolean[] { true,true,true }, ExtensionTable.View.TOTAL);
}
finally {
m_interruptFlag.endTask();
}
}
protected void addKnownConceptSubsumption(Graph<AtomicConcept> knownSubsumptions,AtomicConcept subConcept,AtomicConcept superConcept) {
knownSubsumptions.addEdge(subConcept,superConcept);
}
protected void addKnownRoleSubsumption(Graph<Role> knownSubsumptions,Role subRole,Role superRole) {
knownSubsumptions.addEdge(subRole,superRole);
if (m_usesInverseRoles)
knownSubsumptions.addEdge(subRole.getInverse(),superRole.getInverse());
}
protected void updateKnownSubsumptionsUsingToldSubsumers(Set<DLClause> dlClauses, Graph<AtomicConcept> knownConceptSubsumptions,Set<AtomicConcept> concepts,Graph<Role> knownRoleSubsumptions,Set<Role> roles) {
boolean requiresConceptSubsumers=knownConceptSubsumptions!=null;
boolean requiresRoleSubsumers=knownRoleSubsumptions!=null;
if (requiresConceptSubsumers || requiresRoleSubsumers) {
for (DLClause dlClause : dlClauses) {
if (dlClause.getHeadLength()==1 && dlClause.getBodyLength()==1) {
DLPredicate headPredicate=dlClause.getHeadAtom(0).getDLPredicate();
DLPredicate bodyPredicate=dlClause.getBodyAtom(0).getDLPredicate();
if (requiresConceptSubsumers && headPredicate instanceof AtomicConcept && bodyPredicate instanceof AtomicConcept) {
AtomicConcept headConcept=(AtomicConcept)headPredicate;
AtomicConcept bodyConcept=(AtomicConcept)bodyPredicate;
if (concepts.contains(headConcept) && concepts.contains(bodyConcept))
addKnownConceptSubsumption(knownConceptSubsumptions,bodyConcept,headConcept);
}
else if (requiresRoleSubsumers && headPredicate instanceof AtomicRole && bodyPredicate instanceof AtomicRole) {
AtomicRole headRole=(AtomicRole)headPredicate;
AtomicRole bodyRole=(AtomicRole)bodyPredicate;
if (roles.contains(headRole) && roles.contains(bodyRole)) {
if (dlClause.getBodyAtom(0).getArgument(0)!=dlClause.getHeadAtom(0).getArgument(0))
// r -> s^- and r^- -> s
addKnownRoleSubsumption(knownRoleSubsumptions,InverseRole.create(bodyRole),headRole);
else
// r-> s and r^- -> s^-
addKnownRoleSubsumption(knownRoleSubsumptions,bodyRole,headRole);
}
}
}
m_interruptFlag.checkInterrupt();
}
}
}
protected Hierarchy<AtomicConcept> buildTransitivelyReducedConceptHierarchy(Graph<AtomicConcept> knownSubsumptions) {
final Map<AtomicConcept,GraphNode<AtomicConcept>> allSubsumers=new HashMap<AtomicConcept,GraphNode<AtomicConcept>>();
for (AtomicConcept element : knownSubsumptions.getElements())
allSubsumers.put(element,new GraphNode<AtomicConcept>(element,knownSubsumptions.getSuccessors(element)));
m_interruptFlag.checkInterrupt();
return DeterministicClassification.buildHierarchy(m_topConcept,m_bottomConcept,allSubsumers);
}
public void setToClassifiedConceptHierarchy(Hierarchy<AtomicConcept> atomicConceptHierarchy) {
if (atomicConceptHierarchy!=m_currentConceptHierarchy) {
m_currentConceptHierarchy=atomicConceptHierarchy;
if (m_classesInitialised && m_individuals.length>0) {
for (HierarchyNode<AtomicConcept> node : m_currentConceptHierarchy.getAllNodesSet()) {
if (node.m_representative!=m_bottomConcept) {
AtomicConcept representativeConcept=node.getRepresentative();
Set<Individual> known=new HashSet<Individual>();
Set<Individual> possible=null;
for (AtomicConcept concept : node.getEquivalentElements()) {
if (m_conceptToElement.containsKey(concept)) {
AtomicConceptElement element=m_conceptToElement.get(concept);
known.addAll(element.m_knownInstances);
if (possible==null)
possible=new HashSet<Individual>(element.m_possibleInstances);
else
possible.retainAll(element.m_possibleInstances);
m_conceptToElement.remove(concept);
}
}
if (possible!=null)
possible.removeAll(known);
if (!known.isEmpty()||possible!=null||representativeConcept==m_topConcept)
m_conceptToElement.put(representativeConcept, new AtomicConceptElement(known, possible));
}
}
// clean up known and possibles
Queue<HierarchyNode<AtomicConcept>> toProcess=new LinkedList<HierarchyNode<AtomicConcept>>();
toProcess.addAll(m_currentConceptHierarchy.m_bottomNode.m_parentNodes);
while (!toProcess.isEmpty()) {
HierarchyNode<AtomicConcept> current=toProcess.remove();
AtomicConcept currentConcept=current.getRepresentative();
AtomicConceptElement currentElement=m_conceptToElement.get(currentConcept);
if (currentElement!=null) {
Set<HierarchyNode<AtomicConcept>> ancestors=current.getAncestorNodes();
ancestors.remove(current);
for (HierarchyNode<AtomicConcept> ancestor : ancestors) {
AtomicConcept ancestorConcept=ancestor.getRepresentative();
AtomicConceptElement ancestorElement=m_conceptToElement.get(ancestorConcept);
if (ancestorElement!=null) {
ancestorElement.m_knownInstances.removeAll(currentElement.m_knownInstances);
ancestorElement.m_possibleInstances.removeAll(currentElement.m_knownInstances);
ancestorElement.m_possibleInstances.removeAll(currentElement.m_possibleInstances);
}
}
for (HierarchyNode<AtomicConcept> parent : current.getParentNodes())
if (!toProcess.contains(parent))
toProcess.add(parent);
}
m_interruptFlag.checkInterrupt();
}
}
m_usesClassifiedConceptHierarchy=true;
}
}
protected Hierarchy<RoleElement> buildTransitivelyReducedRoleHierarchy(Graph<Role> knownSubsumptions) {
final Map<Role,GraphNode<Role>> allSubsumers=new HashMap<Role,GraphNode<Role>>();
for (Role role : knownSubsumptions.getElements())
allSubsumers.put(role,new GraphNode<Role>(role,knownSubsumptions.getSuccessors(role)));
m_interruptFlag.checkInterrupt();
return transformRoleHierarchy(DeterministicClassification.buildHierarchy(AtomicRole.TOP_OBJECT_ROLE,AtomicRole.BOTTOM_OBJECT_ROLE,allSubsumers));
}
/**
* Removes the inverses from the given hierarchy and then converts Role hierarchy nodes to RoleElement hierarchy nodes, which can store
* known and possible instances.
* @param roleHierarchy
* @return a hierarchy containing role element nodes and no inverses
*/
protected Hierarchy<RoleElement> transformRoleHierarchy(final Hierarchy<Role> roleHierarchy) {
Hierarchy<AtomicRole> newHierarchy=removeInverses(roleHierarchy);
Hierarchy.Transformer<Role,RoleElement> transformer=new Hierarchy.Transformer<Role,RoleElement>() {
public RoleElement transform(Role role) {
m_interruptFlag.checkInterrupt();
if (!(role instanceof AtomicRole))
throw new IllegalArgumentException("Internal error: The instance manager should only use atomic roles, but here we got a hierarchy element for an inverse role:" + role);
return m_roleElementManager.getRoleElement((AtomicRole)role);
}
public RoleElement determineRepresentative(Role oldRepresentative,Set<RoleElement> newEquivalentElements) {
RoleElement representative=transform(oldRepresentative);
for (RoleElement newEquiv : newEquivalentElements) {
if (!newEquiv.equals(representative)) {
for (Individual individual : newEquiv.m_knownRelations.keySet()) {
Set<Individual> successors=representative.m_knownRelations.get(individual);
if (successors==null) {
successors=new HashSet<Individual>();
representative.m_knownRelations.put(individual, successors);
}
successors.addAll(newEquiv.m_knownRelations.get(individual));
}
for (Individual individual : newEquiv.m_possibleRelations.keySet()) {
Set<Individual> successors=representative.m_possibleRelations.get(individual);
if (successors!=null) {
successors.retainAll(newEquiv.m_possibleRelations.get(individual));
}
}
newEquiv.m_knownRelations.clear();
newEquiv.m_possibleRelations.clear();
}
}
m_interruptFlag.checkInterrupt();
return representative;
}
};
return newHierarchy.transform(transformer,null);
}
protected Hierarchy<AtomicRole> removeInverses(Hierarchy<Role> hierarchy) {
final Map<AtomicRole,GraphNode<AtomicRole>> allSubsumers=new HashMap<AtomicRole,GraphNode<AtomicRole>>();
Set<AtomicRole> toProcess=new HashSet<AtomicRole>();
Set<AtomicRole> visited=new HashSet<AtomicRole>();
toProcess.add(m_bottomRoleElement.m_role);
while (!toProcess.isEmpty()) {
AtomicRole current=toProcess.iterator().next();
visited.add(current);
HierarchyNode<Role> currentNode=hierarchy.getNodeForElement(current);
Set<AtomicRole> atomicRepresentatives=new HashSet<AtomicRole>();
findNextHierarchyNodeWithAtomic(atomicRepresentatives, currentNode);
allSubsumers.put(current,new GraphNode<AtomicRole>(current,atomicRepresentatives));
toProcess.addAll(atomicRepresentatives);
toProcess.removeAll(visited);
m_interruptFlag.checkInterrupt();
}
Hierarchy<AtomicRole> newHierarchy=DeterministicClassification.buildHierarchy(m_topRoleElement.m_role,m_bottomRoleElement.m_role,allSubsumers);
for (AtomicRole element : newHierarchy.m_nodesByElements.keySet()) {
HierarchyNode<Role> oldNode=hierarchy.getNodeForElement(element);
HierarchyNode<AtomicRole> newNode=newHierarchy.getNodeForElement(element);
for (Role equivalent : oldNode.m_equivalentElements) {
if (equivalent instanceof AtomicRole)
newNode.m_equivalentElements.add((AtomicRole)equivalent);
}
m_interruptFlag.checkInterrupt();
}
return newHierarchy;
}
public void setToClassifiedRoleHierarchy(final Hierarchy<Role> roleHierarchy) {
m_currentRoleHierarchy=transformRoleHierarchy(roleHierarchy);
// clean up known and possibles
if (m_propertiesInitialised && m_individuals.length>0) {
Queue<HierarchyNode<RoleElement>> toProcess=new LinkedList<HierarchyNode<RoleElement>>();
toProcess.add(m_currentRoleHierarchy.m_bottomNode);
while (!toProcess.isEmpty()) {
HierarchyNode<RoleElement> current=toProcess.remove();
RoleElement currentRepresentative=current.getRepresentative();
Set<HierarchyNode<RoleElement>> ancestors=current.getAncestorNodes();
ancestors.remove(current);
for (HierarchyNode<RoleElement> ancestor : ancestors) {
RoleElement ancestorRepresentative=ancestor.m_representative;
Map<Individual,Set<Individual>> ancestorKnowRelations=ancestorRepresentative.m_knownRelations;
Map<Individual,Set<Individual>> ancestorPossibleRelations=ancestorRepresentative.m_possibleRelations;
for (Individual individual : currentRepresentative.m_knownRelations.keySet()) {
Set<Individual> successors=ancestorKnowRelations.get(individual);
if (successors!=null) {
successors.removeAll(currentRepresentative.m_knownRelations.get(individual));
if (successors.isEmpty())
ancestorKnowRelations.remove(individual);
}
successors=ancestorPossibleRelations.get(individual);
if (successors!=null) {
successors.removeAll(currentRepresentative.m_knownRelations.get(individual));
if (successors.isEmpty())
ancestorPossibleRelations.remove(individual);
}
}
for (Individual individual : currentRepresentative.m_possibleRelations.keySet()) {
Set<Individual> successors=ancestorPossibleRelations.get(individual);
if (successors!=null) {
successors.removeAll(currentRepresentative.m_possibleRelations.get(individual));
if (successors.isEmpty())
ancestorPossibleRelations.remove(individual);
}
}
}
for (HierarchyNode<RoleElement> parent : current.getParentNodes())
if (!toProcess.contains(parent))
toProcess.add(parent);
m_interruptFlag.checkInterrupt();
}
}
m_usesClassifiedObjectRoleHierarchy=true;
}
protected void findNextHierarchyNodeWithAtomic(Set<AtomicRole> atomicRepresentatives, HierarchyNode<Role> current) {
for (HierarchyNode<Role> successor : current.getParentNodes()) {
Set<AtomicRole> suitable=new HashSet<AtomicRole>();
for (Role role : successor.getEquivalentElements()) {
if (role instanceof AtomicRole)
suitable.add((AtomicRole)role);
}
if (!suitable.isEmpty())
atomicRepresentatives.add(suitable.iterator().next());
else if (successor!=current)
findNextHierarchyNodeWithAtomic(atomicRepresentatives, successor);
}
}
public OWLAxiom[] getAxiomsForReadingOffCompexProperties(OWLDataFactory factory, ReasonerProgressMonitor monitor, int completedSteps, int steps) {
if (m_complexRoles.size()>0) {
int noAdditionalAxioms=0;
List<OWLAxiom> additionalAxioms=new ArrayList<OWLAxiom>();
m_interruptFlag.startTask();
try {
for (;m_currentIndividualIndex<m_individuals.length && noAdditionalAxioms < thresholdForAdditionalAxioms;m_currentIndividualIndex++) {
Individual ind=m_individuals[m_currentIndividualIndex];
for (AtomicRole objectRole : m_complexRoles) {
completedSteps++;
if (monitor!=null)
monitor.reasonerTaskProgressChanged(completedSteps,steps);
OWLObjectProperty objectProperty=factory.getOWLObjectProperty(IRI.create(objectRole.getIRI()));
String indIRI=ind.getIRI();
OWLClass classForIndividual=factory.getOWLClass(IRI.create("internal:individual-concept#"+indIRI));
OWLAxiom axiom=factory.getOWLClassAssertionAxiom(classForIndividual,factory.getOWLNamedIndividual(IRI.create(indIRI)));
additionalAxioms.add(axiom); // A_a(a)
AtomicConcept conceptForRole=AtomicConcept.create("internal:individual-concept#"+objectRole.getIRI()+"#"+indIRI);
OWLClass classForRoleAndIndividual=factory.getOWLClass(IRI.create(conceptForRole.getIRI()));
axiom=factory.getOWLSubClassOfAxiom(classForIndividual,factory.getOWLObjectAllValuesFrom(objectProperty,classForRoleAndIndividual));
additionalAxioms.add(axiom); // A_a implies forall r.A_a^r
noAdditionalAxioms+=2;
m_interruptFlag.checkInterrupt();
}
}
} finally {
m_interruptFlag.endTask();
}
OWLAxiom[] additionalAxiomsArray=new OWLAxiom[additionalAxioms.size()];
return additionalAxioms.toArray(additionalAxiomsArray);
}
else {
m_currentIndividualIndex=m_individuals.length-1;
return new OWLAxiom[0];
}
}
public void initializeKnowAndPossibleClassInstances(Tableau tableau, ReasonerProgressMonitor monitor, int completedSteps, int steps) {
if (!m_classesInitialised) {
m_interruptFlag.startTask();
try {
initializeIndividualsForNodes();
if (!m_propertiesInitialised) {
// nothing has been read-off yet
initializeSameAs();
}
completedSteps=readOffClassInstancesByIndividual(tableau, monitor, completedSteps, steps);
if (!m_readingOffFoundPossibleConceptInstance && m_usesClassifiedConceptHierarchy)
m_realizationCompleted=true;
m_classesInitialised=true;
m_individualsForNodes.clear();
m_canonicalNodeToDetMergedNodes.clear();
m_canonicalNodeToNonDetMergedNodes.clear();
} finally {
m_interruptFlag.endTask();
}
}
}
protected int readOffClassInstancesByIndividual(Tableau tableau, ReasonerProgressMonitor monitor, int completedSteps, int steps) {
for (Individual ind : m_individuals) {
Node nodeForIndividual=m_nodesForIndividuals.get(ind);
// read of concept instances and normal role instances only once, we don't slice that
boolean hasType=readOffTypes(ind,nodeForIndividual);
if (!hasType) {
AtomicConceptElement topElement=m_conceptToElement.get(m_topConcept);
if (topElement==null) {
topElement=new AtomicConceptElement(null, null);
m_conceptToElement.put(m_topConcept, topElement);
}
topElement.m_knownInstances.add(ind);
}
completedSteps++;
if (monitor!=null)
monitor.reasonerTaskProgressChanged(completedSteps,steps);
m_interruptFlag.checkInterrupt();
}
return completedSteps;
}
public int initializeKnowAndPossiblePropertyInstances(Tableau tableau, ReasonerProgressMonitor monitor, int startIndividualIndex, int completedSteps, int steps) {
if (!m_propertiesInitialised) {
m_interruptFlag.startTask();
try {
initializeIndividualsForNodes();
if (!m_classesInitialised)
// nothing has been read-off yet
initializeSameAs();
completedSteps=readOffPropertyInstancesByIndividual(tableau,m_individualsForNodes, monitor, completedSteps, steps, startIndividualIndex);
if (m_currentIndividualIndex>=m_individuals.length-1) {
// we are done now with everything
if (!m_readingOffFoundPossiblePropertyInstance)
m_roleRealizationCompleted=true;
m_propertiesInitialised=true;
}
m_individualsForNodes.clear();
} finally {
m_interruptFlag.endTask();
}
}
return completedSteps;
}
protected int readOffPropertyInstancesByIndividual(Tableau tableau,Map<Node,Individual> individualsForNodes, ReasonerProgressMonitor monitor, int completedSteps, int steps, int startIndividualIndex) {
// first round we go over all individuals
int endIndex=(startIndividualIndex==0) ? m_individuals.length : m_currentIndividualIndex;
for (int index=startIndividualIndex;index<endIndex;index++) {
Individual ind=m_individuals[index];
Node nodeForIndividual=m_nodesForIndividuals.get(ind);
if (startIndividualIndex==0) {
// read of normal role instances only once, we don't slice that
// if the node was merged, we don't read off anything, this is handled, when we process the canonical node for the merged one
if (!nodeForIndividual.isMerged())
readOffPropertyInstances(nodeForIndividual);
completedSteps++;
if (monitor!=null)
monitor.reasonerTaskProgressChanged(completedSteps,steps);
}
// read-off complex role instances only for the slice for which extra axioms have been added
if (index<m_currentIndividualIndex)
completedSteps=readOffComplexRoleSuccessors(ind,nodeForIndividual, monitor, completedSteps, steps);
m_interruptFlag.checkInterrupt();
}
return completedSteps;
}
protected void initializeIndividualsForNodes() {
for (Individual ind : m_individuals) {
Node node=m_nodesForIndividuals.get(ind);
m_individualsForNodes.put(node, ind);
if (node.isMerged()) {
Node canonicalNode=node.getCanonicalNode();
if (node.getCanonicalNodeDependencySet()==null) {
// deterministically merged
Set<Node> merged=m_canonicalNodeToDetMergedNodes.get(canonicalNode);
if (merged==null) {
merged=new HashSet<Node>();
m_canonicalNodeToDetMergedNodes.put(canonicalNode,merged);
}
merged.add(node);
} else {
// nondeterministically merged
Set<Node> merged=m_canonicalNodeToNonDetMergedNodes.get(canonicalNode);
if (merged==null) {
merged=new HashSet<Node>();
m_canonicalNodeToNonDetMergedNodes.put(canonicalNode,merged);
}
merged.add(node);
}
}
m_interruptFlag.checkInterrupt();
}
}
protected void initializeSameAs() {
m_individualToPossibleEquivalenceClass=new HashMap<Set<Individual>, Set<Set<Individual>>>();
for (Node node : m_individualsForNodes.keySet()) {
Node mergedInto=node.getMergedInto();
if (mergedInto!=null) {
Individual individual1=m_individualsForNodes.get(node);
Individual individual2=m_individualsForNodes.get(mergedInto);
Set<Individual> individual1Equivalences=m_individualToEquivalenceClass.get(individual1);
Set<Individual> individual2Equivalences=m_individualToEquivalenceClass.get(individual2);
if (node.getMergedIntoDependencySet().isEmpty()) {
individual1Equivalences.addAll(individual2Equivalences);
m_individualToEquivalenceClass.put(individual2, individual1Equivalences);
}
else {
Set<Set<Individual>> possibleEquivalenceClasses=m_individualToPossibleEquivalenceClass.get(individual1Equivalences);
if (possibleEquivalenceClasses==null) {
possibleEquivalenceClasses=new HashSet<Set<Individual>>();
m_individualToPossibleEquivalenceClass.put(individual1Equivalences,possibleEquivalenceClasses);
}
possibleEquivalenceClasses.add(individual2Equivalences);
}
}
m_interruptFlag.checkInterrupt();
}
}
protected boolean readOffTypes(Individual ind, Node nodeForIndividual) {
boolean hasBeenAdded=false;
m_binaryRetrieval1Bound.getBindingsBuffer()[1]=nodeForIndividual.getCanonicalNode();
m_binaryRetrieval1Bound.open();
Object[] tupleBuffer=m_binaryRetrieval1Bound.getTupleBuffer();
while (!m_binaryRetrieval1Bound.afterLast()) {
Object predicate=tupleBuffer[0];
if (predicate instanceof AtomicConcept) {
AtomicConcept atomicConcept=(AtomicConcept)predicate;
if (!atomicConcept.equals(m_topConcept) && !Prefixes.isInternalIRI(atomicConcept.getIRI())) {
HierarchyNode<AtomicConcept> node=m_currentConceptHierarchy.getNodeForElement(atomicConcept);
AtomicConcept representative=node.getRepresentative();
AtomicConceptElement element=m_conceptToElement.get(representative);
if (element==null) {
element=new AtomicConceptElement(null, null);
m_conceptToElement.put(representative, element);
}
hasBeenAdded=true;
if (m_binaryRetrieval1Bound.getDependencySet().isEmpty())
addKnownConceptInstance(node, element, ind);
else {
addPossibleConceptInstance(node, element, ind);
m_readingOffFoundPossibleConceptInstance=true;
}
}
}
m_interruptFlag.checkInterrupt();
m_binaryRetrieval1Bound.next();
}
return hasBeenAdded;
}
protected void readOffPropertyInstances(Node nodeForIndividual) {
// nodeForIndividual is always a canonical node
m_ternaryRetrieval1Bound.getBindingsBuffer()[1]=nodeForIndividual;
m_ternaryRetrieval1Bound.open();
Object[] tupleBuffer=m_ternaryRetrieval1Bound.getTupleBuffer();
while (!m_ternaryRetrieval1Bound.afterLast()) {
Object roleObject=tupleBuffer[0];
Node successorNode=((Node)tupleBuffer[2]);
if (roleObject instanceof AtomicRole && !successorNode.isMerged() && successorNode.getNodeType()==NodeType.NAMED_NODE && m_individualsForNodes.containsKey(successorNode) && successorNode.isActive()) {
AtomicRole atomicrole=(AtomicRole)roleObject;
if (!atomicrole.equals(AtomicRole.TOP_OBJECT_ROLE) && m_roleElementManager.m_roleToElement.containsKey(atomicrole)) {
// the latter condition ensures that we do not accidentally try and read of something for data properties
RoleElement representative=m_currentRoleHierarchy.getNodeForElement(m_roleElementManager.getRoleElement(atomicrole)).getRepresentative();
// determine equivalent and possibly equivalent named nodes for the node
Set<Node> equivalentToNode=m_canonicalNodeToDetMergedNodes.get(nodeForIndividual);
if (equivalentToNode==null)
equivalentToNode=new HashSet<Node>();
equivalentToNode.add(nodeForIndividual);
Set<Node> possiblyEquivalentToNode=m_canonicalNodeToNonDetMergedNodes.get(nodeForIndividual);
if (possiblyEquivalentToNode==null)
possiblyEquivalentToNode=new HashSet<Node>();
// determine equivalent and possibly equivalent named nodes for the successor node
Set<Node> equivalentToSuccessor=m_canonicalNodeToDetMergedNodes.get(successorNode);
if (equivalentToSuccessor==null)
equivalentToSuccessor=new HashSet<Node>();
equivalentToSuccessor.add(successorNode);
Set<Node> possiblyEquivalentToSuccessor=m_canonicalNodeToNonDetMergedNodes.get(successorNode);
if (possiblyEquivalentToSuccessor==null)
possiblyEquivalentToSuccessor=new HashSet<Node>();
for (Node sourceNode : equivalentToNode) {
Individual sourceIndividual=m_individualsForNodes.get(sourceNode);
for (Node targetNode : equivalentToSuccessor) {
Individual targetIndividual=m_individualsForNodes.get(targetNode);
if (m_ternaryRetrieval1Bound.getDependencySet().isEmpty()) {
addKnownRoleInstance(representative, sourceIndividual, targetIndividual);
} else {
m_readingOffFoundPossiblePropertyInstance=true;
addPossibleRoleInstance(representative, sourceIndividual, targetIndividual);
}
}
for (Node targetNode : possiblyEquivalentToSuccessor) {
Individual targetIndividual=m_individualsForNodes.get(targetNode);
m_readingOffFoundPossiblePropertyInstance=true;
addPossibleRoleInstance(representative, sourceIndividual, targetIndividual);
}
}
for (Node sourceNode : possiblyEquivalentToNode) {
Individual sourceIndividual=m_individualsForNodes.get(sourceNode);
possiblyEquivalentToSuccessor.addAll(equivalentToSuccessor);
for (Node targetNode : possiblyEquivalentToSuccessor) {
Individual targetIndividual=m_individualsForNodes.get(targetNode);
m_readingOffFoundPossiblePropertyInstance=true;
addPossibleRoleInstance(representative, sourceIndividual, targetIndividual);
}
}
}
}
m_interruptFlag.checkInterrupt();
m_ternaryRetrieval1Bound.next();
}
}
protected int readOffComplexRoleSuccessors(Individual ind, Node nodeForIndividual, ReasonerProgressMonitor monitor, int completedSteps, int steps) {
String indIRI=ind.getIRI();
AtomicConcept conceptForRole;
for (AtomicRole atomicRole : m_complexRoles) {
conceptForRole=AtomicConcept.create("internal:individual-concept#"+atomicRole.getIRI()+"#"+indIRI);
m_binaryRetrieval0Bound.getBindingsBuffer()[0]=conceptForRole;
m_binaryRetrieval0Bound.open();
Object[] tupleBuffer=m_binaryRetrieval0Bound.getTupleBuffer();
while (!m_binaryRetrieval0Bound.afterLast()) {
Node node=(Node)tupleBuffer[1];
if (node.isActive() && node.getNodeType()==NodeType.NAMED_NODE && m_individualsForNodes.containsKey(node)) {
RoleElement representative=m_currentRoleHierarchy.getNodeForElement(m_roleElementManager.getRoleElement(atomicRole)).getRepresentative();
//Individual successor=m_individualsForNodes.get(node.getCanonicalNode());
// determine equivalent and possibly equivalent named nodes for the successor node
Set<Node> equivalentToSuccessor=m_canonicalNodeToDetMergedNodes.get(node);
if (equivalentToSuccessor==null)
equivalentToSuccessor=new HashSet<Node>();
equivalentToSuccessor.add(node);
Set<Node> possiblyEquivalentToSuccessor=m_canonicalNodeToNonDetMergedNodes.get(node);
if (possiblyEquivalentToSuccessor==null)
possiblyEquivalentToSuccessor=new HashSet<Node>();
for (Node targetNode : equivalentToSuccessor) {
Individual targetIndividual=m_individualsForNodes.get(targetNode);
if (m_binaryRetrieval0Bound.getDependencySet().isEmpty()) {
addKnownRoleInstance(representative, ind, targetIndividual);
} else {
m_readingOffFoundPossiblePropertyInstance=true;
addPossibleRoleInstance(representative, ind, targetIndividual);
}
}
for (Node targetNode : possiblyEquivalentToSuccessor) {
Individual targetIndividual=m_individualsForNodes.get(targetNode);
m_readingOffFoundPossiblePropertyInstance=true;
addPossibleRoleInstance(representative, ind, targetIndividual);
}
}
m_interruptFlag.checkInterrupt();
m_binaryRetrieval0Bound.next();
}
completedSteps++;
if (monitor!=null)
monitor.reasonerTaskProgressChanged(completedSteps,steps);
}
return completedSteps;
}
protected void addKnownConceptInstance(HierarchyNode<AtomicConcept> currentNode, AtomicConceptElement element, Individual instance) {
Set<HierarchyNode<AtomicConcept>> nodes=currentNode.getDescendantNodes();
for (HierarchyNode<AtomicConcept> node : nodes) {
AtomicConceptElement descendantElement=m_conceptToElement.get(node.getRepresentative());
if (descendantElement!=null && descendantElement.m_knownInstances.contains(instance))
return;
m_interruptFlag.checkInterrupt();
}
element.m_knownInstances.add(instance);
nodes=currentNode.getAncestorNodes();
nodes.remove(currentNode);
for (HierarchyNode<AtomicConcept> node : nodes) {
AtomicConceptElement ancestorElement=m_conceptToElement.get(node.getRepresentative());
if (ancestorElement!=null) {
ancestorElement.m_knownInstances.remove(instance);
ancestorElement.m_possibleInstances.remove(instance);
}
}
}
protected void addPossibleConceptInstance(HierarchyNode<AtomicConcept> currentNode, AtomicConceptElement element, Individual instance) {
Set<HierarchyNode<AtomicConcept>> nodes=currentNode.getDescendantNodes();
for (HierarchyNode<AtomicConcept> node : nodes) {
AtomicConceptElement descendantElement=m_conceptToElement.get(node.getRepresentative());
if (descendantElement!=null && (descendantElement.m_knownInstances.contains(instance) || descendantElement.m_possibleInstances.contains(instance)))
return;
m_interruptFlag.checkInterrupt();
}
element.m_possibleInstances.add(instance);
nodes=currentNode.getAncestorNodes();
nodes.remove(currentNode);
for (HierarchyNode<AtomicConcept> node : nodes) {
AtomicConceptElement ancestorElement=m_conceptToElement.get(node.getRepresentative());
if (ancestorElement!=null) {
ancestorElement.m_possibleInstances.remove(instance);
if (ancestorElement.m_possibleInstances.isEmpty() && ancestorElement.m_knownInstances.isEmpty() && node.getRepresentative()!=m_topConcept)
m_conceptToElement.remove(node.getRepresentative());
}
m_interruptFlag.checkInterrupt();
}
}
protected void addKnownRoleInstance(RoleElement element, Individual individual1, Individual individual2) {
if (!element.equals(m_topRoleElement)) {
HierarchyNode<RoleElement> currentNode=m_currentRoleHierarchy.getNodeForElement(element);
Set<HierarchyNode<RoleElement>> nodes=currentNode.getDescendantNodes();
for (HierarchyNode<RoleElement> node : nodes) {
for (RoleElement descendantElement : node.getEquivalentElements()) {
if (descendantElement.isKnown(individual1,individual2))
return;
}
m_interruptFlag.checkInterrupt();
}
element.addKnown(individual1, individual2);
nodes=currentNode.getAncestorNodes();
nodes.remove(currentNode);
for (HierarchyNode<RoleElement> node : nodes) {
node.getRepresentative().removeKnown(individual1, individual2);
m_interruptFlag.checkInterrupt();
}
}
}
protected void addPossibleRoleInstance(RoleElement element, Individual individual1, Individual individual2) {
if (!element.equals(m_topRoleElement)) {
HierarchyNode<RoleElement> currentNode=m_currentRoleHierarchy.getNodeForElement(element);
Set<HierarchyNode<RoleElement>> nodes=currentNode.getDescendantNodes();
for (HierarchyNode<RoleElement> node : nodes) {
for (RoleElement descendantElement : node.getEquivalentElements()) {
if (descendantElement.isPossible(individual1, individual2))
return;
}
m_interruptFlag.checkInterrupt();
}
element.addPossible(individual1, individual2);
nodes=currentNode.getAncestorNodes();
nodes.remove(currentNode);
for (HierarchyNode<RoleElement> node : nodes) {
for (RoleElement ancestorElement : node.getEquivalentElements()) {
if (ancestorElement.isPossible(individual1,individual2))
ancestorElement.removePossible(individual1, individual2);
}
m_interruptFlag.checkInterrupt();
}
}
}
public void setInconsistent() {
m_isInconsistent=true;
m_realizationCompleted=true;
m_roleRealizationCompleted=true;
m_usesClassifiedConceptHierarchy=true;
m_usesClassifiedObjectRoleHierarchy=true;
m_currentConceptHierarchy=null;
m_currentRoleHierarchy=null;
}
public void realize(ReasonerProgressMonitor monitor) {
assert m_usesClassifiedConceptHierarchy==true;
if (m_readingOffFoundPossibleConceptInstance && !m_realizationCompleted) {
if (monitor!=null)
monitor.reasonerTaskStarted("Computing instances for all classes");
int numHierarchyNodes=m_currentConceptHierarchy.m_nodesByElements.values().size();
int currentHierarchyNode=0;
Queue<HierarchyNode<AtomicConcept>> toProcess=new LinkedList<HierarchyNode<AtomicConcept>>();
Set<HierarchyNode<AtomicConcept>> visited=new HashSet<HierarchyNode<AtomicConcept>>();
toProcess.addAll(m_currentConceptHierarchy.m_bottomNode.m_parentNodes);
while (!toProcess.isEmpty()) {
if (monitor!=null)
monitor.reasonerTaskProgressChanged(currentHierarchyNode,numHierarchyNodes);
HierarchyNode<AtomicConcept> current=toProcess.remove();
visited.add(current);
currentHierarchyNode++;
AtomicConcept atomicConcept=current.getRepresentative();
AtomicConceptElement atomicConceptElement=m_conceptToElement.get(atomicConcept);
if (atomicConceptElement!=null) {
Set<HierarchyNode<AtomicConcept>> parents=current.getParentNodes();
for (HierarchyNode<AtomicConcept> parent : parents) {
if (!visited.contains(parent) && !toProcess.contains(parent))
toProcess.add(parent);
}
if (atomicConceptElement.hasPossibles()) {
Set<Individual> nonInstances=new HashSet<Individual>();
for (Individual individual : atomicConceptElement.getPossibleInstances()) {
if (isInstance(individual, atomicConcept))
atomicConceptElement.m_knownInstances.add(individual);
else
nonInstances.add(individual);
}
atomicConceptElement.m_possibleInstances.clear();
for (HierarchyNode<AtomicConcept> parent : parents) {
AtomicConcept parentRepresentative=parent.getRepresentative();
AtomicConceptElement parentElement=m_conceptToElement.get(parentRepresentative);
if (parentElement==null) {
parentElement=new AtomicConceptElement(null, nonInstances);
m_conceptToElement.put(parentRepresentative, parentElement);
}
else if (parentRepresentative.equals(m_topConcept))
m_conceptToElement.get(m_topConcept).m_knownInstances.addAll(nonInstances);
else
parentElement.addPossibles(nonInstances);
}
}
}
m_interruptFlag.checkInterrupt();
}
if (monitor!=null)
monitor.reasonerTaskStopped();
}
m_realizationCompleted=true;
}
public void realizeObjectRoles(ReasonerProgressMonitor monitor) {
if (m_readingOffFoundPossiblePropertyInstance && !m_roleRealizationCompleted) {
if (monitor!=null)
monitor.reasonerTaskStarted("Computing instances for all object properties...");
int numHierarchyNodes=m_currentRoleHierarchy.m_nodesByElements.values().size();
int currentHierarchyNode=0;
Queue<HierarchyNode<RoleElement>> toProcess=new LinkedList<HierarchyNode<RoleElement>>();
Set<HierarchyNode<RoleElement>> visited=new HashSet<HierarchyNode<RoleElement>>();
toProcess.add(m_currentRoleHierarchy.m_bottomNode);
while (!toProcess.isEmpty()) {
if (monitor!=null)
monitor.reasonerTaskProgressChanged(currentHierarchyNode,numHierarchyNodes);
HierarchyNode<RoleElement> current=toProcess.remove();
visited.add(current);
currentHierarchyNode++;
RoleElement roleElement=current.getRepresentative();
Role role=roleElement.getRole();
Set<HierarchyNode<RoleElement>> parents=current.getParentNodes();
for (HierarchyNode<RoleElement> parent : parents)
if (!toProcess.contains(parent) && !visited.contains(parent))
toProcess.add(parent);
if (roleElement.hasPossibles()) {
for (Individual individual : roleElement.m_possibleRelations.keySet()) {
Set<Individual> nonInstances=new HashSet<Individual>();
for (Individual successor : roleElement.m_possibleRelations.get(individual)) {
if (isRoleInstance(role, individual, successor))
roleElement.addKnown(individual, successor);
else {
nonInstances.add(individual);
}
}
for (HierarchyNode<RoleElement> parent : parents) {
RoleElement parentRepresentative=parent.getRepresentative();
if (!parentRepresentative.equals(m_topRoleElement))
parentRepresentative.addPossibles(individual, nonInstances);
}
}
roleElement.m_possibleRelations.clear();
}
m_interruptFlag.checkInterrupt();
}
if (monitor!=null)
monitor.reasonerTaskStopped();
}
m_roleRealizationCompleted=true;
}
public Set<HierarchyNode<AtomicConcept>> getTypes(Individual individual,boolean direct) {
if (m_isInconsistent)
return Collections.singleton(m_currentConceptHierarchy.m_bottomNode);
Set<HierarchyNode<AtomicConcept>> result=new HashSet<HierarchyNode<AtomicConcept>>();
assert !direct || m_usesClassifiedConceptHierarchy;
Queue<HierarchyNode<AtomicConcept>> toProcess=new LinkedList<HierarchyNode<AtomicConcept>>();
toProcess.add(m_currentConceptHierarchy.m_bottomNode);
while (!toProcess.isEmpty()) {
HierarchyNode<AtomicConcept> current=toProcess.remove();
Set<HierarchyNode<AtomicConcept>> parents=current.getParentNodes();
AtomicConcept atomicConcept=current.getRepresentative();
AtomicConceptElement atomicConceptElement=m_conceptToElement.get(atomicConcept);
if (atomicConceptElement!=null && atomicConceptElement.isPossible(individual)) {
if (isInstance(individual, atomicConcept)) {
atomicConceptElement.setToKnown(individual);
}
else {
for (HierarchyNode<AtomicConcept> parent : parents) {
AtomicConcept parentRepresentative=parent.getRepresentative();
AtomicConceptElement parentElement=m_conceptToElement.get(parentRepresentative);
if (parentElement==null) {
parentElement=new AtomicConceptElement(null, null);
m_conceptToElement.put(parentRepresentative,parentElement);
}
parentElement.addPossible(individual);
}
}
}
if (atomicConceptElement!=null && atomicConceptElement.isKnown(individual)) {
if (direct)
result.add(current);
else
result.addAll(current.getAncestorNodes());
}
else {
for (HierarchyNode<AtomicConcept> parent : parents)
if (!toProcess.contains(parent))
toProcess.add(parent);
}
}
return result;
}
public boolean hasType(Individual individual,AtomicConcept atomicConcept,boolean direct) {
HierarchyNode<AtomicConcept> node=m_currentConceptHierarchy.getNodeForElement(atomicConcept);
if (node==null)
return false;
return hasType(individual, node, direct);
}
public boolean hasType(Individual individual,HierarchyNode<AtomicConcept> node,boolean direct) {
assert !direct || m_usesClassifiedConceptHierarchy;
AtomicConcept representative=node.getRepresentative();
if (representative==m_bottomConcept)
return false;
AtomicConceptElement element=m_conceptToElement.get(representative);
if ((element!=null && element.isKnown(individual)) || (!direct && node==m_currentConceptHierarchy.m_topNode))
return true;
if (element!=null && element.isPossible(individual)) {
if (isInstance(individual, representative)) {
element.setToKnown(individual);
return true;
}
else {
element.m_possibleInstances.remove(individual);
if (element.m_knownInstances.isEmpty() && element.m_possibleInstances.isEmpty() && representative!=m_topConcept)
m_conceptToElement.remove(representative);
for (HierarchyNode<AtomicConcept> parent : node.getParentNodes()) {
AtomicConcept parentConcept=parent.getRepresentative();
AtomicConceptElement parentElement=m_conceptToElement.get(parentConcept);
if (parentElement==null) {
parentElement=new AtomicConceptElement(null, null);
m_conceptToElement.put(parentConcept, parentElement);
}
parentElement.addPossible(individual);
}
}
}
else if (!direct)
for (HierarchyNode<AtomicConcept> child : node.getChildNodes())
if (hasType(individual, child, false))
return true;
return false;
}
public Set<Individual> getInstances(AtomicConcept atomicConcept, boolean direct) {
Set<Individual> result=new HashSet<Individual>();
HierarchyNode<AtomicConcept> node=m_currentConceptHierarchy.getNodeForElement(atomicConcept);
if (node==null) return result; // unknown concept
getInstancesForNode(node,result,direct);
return result;
}
public Set<Individual> getInstances(HierarchyNode<AtomicConcept> node,boolean direct) {
Set<Individual> result=new HashSet<Individual>();
HierarchyNode<AtomicConcept> nodeFromCurrentHierarchy=m_currentConceptHierarchy.getNodeForElement(node.m_representative);
if (nodeFromCurrentHierarchy==null) {
// complex concept instances
if (!direct) {
for (HierarchyNode<AtomicConcept> child : node.getChildNodes()) {
getInstancesForNode(child, result, direct);
}
}
}
else
getInstancesForNode(nodeFromCurrentHierarchy, result, direct);
return result;
}
protected void getInstancesForNode(HierarchyNode<AtomicConcept> node,Set<Individual> result,boolean direct) {
assert !direct || m_usesClassifiedConceptHierarchy;
AtomicConcept representative=node.getRepresentative();
if (!direct && representative.equals(m_topConcept)) {
for (Individual individual : m_individuals)
if (isResultRelevantIndividual(individual))
result.add(individual);
return;
}
AtomicConceptElement representativeElement=m_conceptToElement.get(representative);
if (representativeElement!=null) {
Set<Individual> possibleInstances=representativeElement.getPossibleInstances();
if (!possibleInstances.isEmpty()) {
for (Individual possibleInstance : new HashSet<Individual>(possibleInstances)) {
if (isInstance(possibleInstance, representative))
representativeElement.setToKnown(possibleInstance);
else {
representativeElement.m_possibleInstances.remove(possibleInstance);
if (representativeElement.m_knownInstances.isEmpty() && representativeElement.m_possibleInstances.isEmpty() && representative!=m_topConcept)
m_conceptToElement.remove(representative);
for (HierarchyNode<AtomicConcept> parent : node.getParentNodes()) {
AtomicConcept parentConcept=parent.getRepresentative();
AtomicConceptElement parentElement=m_conceptToElement.get(parentConcept);
if (parentElement==null) {
parentElement=new AtomicConceptElement(null, null);
m_conceptToElement.put(parentConcept, parentElement);
}
parentElement.addPossible(possibleInstance);
}
}
}
}
for (Individual individual : representativeElement.getKnownInstances()) {
if (isResultRelevantIndividual(individual)) {
boolean isDirect=true;
if (direct) {
for (HierarchyNode<AtomicConcept> child : node.getChildNodes()) {
if (hasType(individual, child, false)) {
isDirect=false;
break;
}
}
}
if (!direct || isDirect)
result.add(individual);
}
}
}
if (!direct)
for (HierarchyNode<AtomicConcept> child : node.getChildNodes())
if (child!=m_currentConceptHierarchy.m_bottomNode)
getInstancesForNode(child, result, false);
}
public boolean hasObjectRoleRelationship(AtomicRole role, Individual individual1, Individual individual2) {
RoleElement element=m_roleElementManager.getRoleElement(role);
HierarchyNode<RoleElement> currentNode=m_currentRoleHierarchy.getNodeForElement(element);
if (currentNode==null)
return false;
return hasObjectRoleRelationship(currentNode, individual1, individual2);
}
public boolean hasObjectRoleRelationship(HierarchyNode<RoleElement> node,Individual individual1,Individual individual2) {
RoleElement representativeElement=node.getRepresentative();
if (representativeElement.isKnown(individual1, individual2) || representativeElement.equals(m_topRoleElement))
return true;
List<Individual> individuals=Arrays.asList(m_individuals);
boolean containsUnknown=!individuals.contains(individual1) || !individuals.contains(individual2);
if (representativeElement.isPossible(individual1,individual2) || containsUnknown) {
if (isRoleInstance(representativeElement.getRole(),individual1,individual2)) {
if (!containsUnknown)
representativeElement.setToKnown(individual1,individual2);
return true;
}
else
for (HierarchyNode<RoleElement> parent : node.getParentNodes())
parent.getRepresentative().addPossible(individual1,individual2);
}
else
for (HierarchyNode<RoleElement> child : node.getChildNodes())
if (hasObjectRoleRelationship(child,individual1,individual2))
return true;
return false;
}
public Map<Individual,Set<Individual>> getObjectPropertyInstances(AtomicRole role) {
Map<Individual,Set<Individual>> result=new HashMap<Individual, Set<Individual>>();
HierarchyNode<RoleElement> node=m_currentRoleHierarchy.getNodeForElement(m_roleElementManager.getRoleElement(role));
if (node==null)
return result;
getObjectPropertyInstances(node,result);
return result;
}
protected void getObjectPropertyInstances(HierarchyNode<RoleElement> node,Map<Individual,Set<Individual>> result) {
RoleElement representativeElement=node.getRepresentative();
if (representativeElement.equals(m_topRoleElement) || m_isInconsistent) {
Set<Individual> allResultRelevantIndividuals=new HashSet<Individual>();
for (Individual individual : m_individuals)
if (isResultRelevantIndividual(individual)) {
allResultRelevantIndividuals.add(individual);
result.put(individual, allResultRelevantIndividuals);
}
return;
}
Map<Individual,Set<Individual>> possibleInstances=representativeElement.getPossibleRelations();
for (Individual possibleInstance : new HashSet<Individual>(possibleInstances.keySet())) {
for (Individual possibleSuccessor : new HashSet<Individual>(possibleInstances.get(possibleInstance))) {
if (isRoleInstance(representativeElement.getRole(),possibleInstance,possibleSuccessor))
representativeElement.setToKnown(possibleInstance,possibleSuccessor);
else
for (HierarchyNode<RoleElement> parent : node.getParentNodes())
parent.getRepresentative().addPossible(possibleInstance,possibleSuccessor);
}
}
Map<Individual,Set<Individual>> knownInstances=representativeElement.getKnownRelations();
for (Individual instance1 : knownInstances.keySet()) {
if (isResultRelevantIndividual(instance1)) {
Set<Individual> successors=result.get(instance1);
boolean isNew=false;
if (successors==null) {
successors=new HashSet<Individual>();
isNew=true;
}
for (Individual instance2 : knownInstances.get(instance1)) {
if (isResultRelevantIndividual(instance2)) {
successors.add(instance2);
}
}
if (isNew && !successors.isEmpty())
result.put(instance1, successors);
}
}
for (HierarchyNode<RoleElement> child : node.getChildNodes())
getObjectPropertyInstances(child, result);
}
public Set<Individual> getObjectPropertyValues(AtomicRole role,Individual individual) {
Set<Individual> result=new HashSet<Individual>();
HierarchyNode<RoleElement> node=m_currentRoleHierarchy.getNodeForElement(m_roleElementManager.getRoleElement(role));;
getObjectPropertyValues(node,individual, result);
return result;
}
public Set<Individual> getObjectPropertySubjects(AtomicRole role,Individual individual) {
Set<Individual> result=new HashSet<Individual>();
HierarchyNode<RoleElement> node=m_currentRoleHierarchy.getNodeForElement(m_roleElementManager.getRoleElement(role));
getObjectPropertySubjects(node, individual, result);
return result;
}
protected void getObjectPropertySubjects(HierarchyNode<RoleElement> node, Individual object, Set<Individual> result) {
RoleElement representativeElement=node.getRepresentative();
if (representativeElement.equals(m_topRoleElement) || m_isInconsistent) {
for (Individual ind : m_individuals)
if (isResultRelevantIndividual(ind))
result.add(ind);
return;
}
Map<Individual,Set<Individual>> relevantRelations=representativeElement.getKnownRelations();
for (Individual subject : new HashSet<Individual>(relevantRelations.keySet())) {
if (isResultRelevantIndividual(subject) && relevantRelations.get(subject).contains(object))
result.add(subject);
}
relevantRelations=representativeElement.getPossibleRelations();
for (Individual possibleSubject : new HashSet<Individual>(relevantRelations.keySet())) {
if (isResultRelevantIndividual(possibleSubject) && relevantRelations.get(possibleSubject).contains(object) && isRoleInstance(representativeElement.getRole(),possibleSubject,object)) {
representativeElement.setToKnown(possibleSubject,object);
result.add(possibleSubject);
}
else
for (HierarchyNode<RoleElement> parent : node.getParentNodes())
parent.getRepresentative().addPossible(possibleSubject,object);
}
for (HierarchyNode<RoleElement> child : node.getChildNodes())
getObjectPropertySubjects(child, object, result);
}
protected void getObjectPropertyValues(HierarchyNode<RoleElement> node, Individual subject, Set<Individual> result) {
RoleElement representativeElement=node.getRepresentative();
if (representativeElement.equals(m_topRoleElement) || m_isInconsistent) {
for (Individual ind : m_individuals)
if (isResultRelevantIndividual(ind))
result.add(ind);
return;
}
Set<Individual> possibleSuccessors=representativeElement.getPossibleRelations().get(subject);
if (possibleSuccessors!=null) {
for (Individual possibleSuccessor : new HashSet<Individual>(possibleSuccessors)) {
if (isRoleInstance(representativeElement.getRole(),subject,possibleSuccessor))
representativeElement.setToKnown(subject,possibleSuccessor);
else
for (HierarchyNode<RoleElement> parent : node.getParentNodes())
parent.getRepresentative().addPossible(subject,possibleSuccessor);
}
}
Set<Individual> knownSuccessors=representativeElement.getKnownRelations().get(subject);
if (knownSuccessors!=null) {
for (Individual successor : knownSuccessors)
if (isResultRelevantIndividual(successor))
result.add(successor);
}
for (HierarchyNode<RoleElement> child : node.getChildNodes())
getObjectPropertyValues(child, subject, result);
}
public Set<Individual> getSameAsIndividuals(Individual individual) {
Set<Individual> equivalenceClass=m_individualToEquivalenceClass.get(individual);
Set<Set<Individual>> possiblySameEquivalenceClasses=m_individualToPossibleEquivalenceClass.get(equivalenceClass);
if (possiblySameEquivalenceClasses!=null) {
while (!possiblySameEquivalenceClasses.isEmpty()) {
Set<Individual> possiblyEquivalentClass=possiblySameEquivalenceClasses.iterator().next();
possiblySameEquivalenceClasses.remove(possiblyEquivalentClass);
if (possiblySameEquivalenceClasses.isEmpty())
m_individualToPossibleEquivalenceClass.remove(equivalenceClass);
Individual possiblyEquivalentIndividual=possiblyEquivalentClass.iterator().next();
if (isSameIndividual(equivalenceClass.iterator().next(), possiblyEquivalentIndividual)) {
equivalenceClass.addAll(possiblyEquivalentClass);
equivalenceClass.addAll(m_individualToEquivalenceClass.get(possiblyEquivalentIndividual));
for (Individual nowKnownEquivalent : possiblyEquivalentClass)
m_individualToEquivalenceClass.put(nowKnownEquivalent, equivalenceClass);
}
else {
Set<Set<Individual>> possiblyEquivalentToNowKnownInequivalent=m_individualToPossibleEquivalenceClass.get(possiblyEquivalentClass);
if (possiblyEquivalentToNowKnownInequivalent!=null && possiblyEquivalentToNowKnownInequivalent.contains(equivalenceClass)) {
possiblyEquivalentToNowKnownInequivalent.remove(equivalenceClass);
if (possiblyEquivalentToNowKnownInequivalent.isEmpty())
m_individualToPossibleEquivalenceClass.remove(possiblyEquivalentClass);
}
}
}
}
for (Set<Individual> otherEquivalenceClass : new HashSet<Set<Individual>>(m_individualToPossibleEquivalenceClass.keySet())) {
if (otherEquivalenceClass!=equivalenceClass && m_individualToPossibleEquivalenceClass.get(otherEquivalenceClass).contains(equivalenceClass)) {
if (isSameIndividual(equivalenceClass.iterator().next(), otherEquivalenceClass.iterator().next())) {
m_individualToPossibleEquivalenceClass.get(otherEquivalenceClass).remove(equivalenceClass);
if (m_individualToPossibleEquivalenceClass.get(otherEquivalenceClass).isEmpty())
m_individualToPossibleEquivalenceClass.remove(otherEquivalenceClass);
for (Individual nowKnownEquivalent : otherEquivalenceClass)
m_individualToEquivalenceClass.put(nowKnownEquivalent, equivalenceClass);
equivalenceClass.addAll(otherEquivalenceClass);
}
}
}
return equivalenceClass;
}
public boolean isSameIndividual(Individual individual1, Individual individual2) {
return (!m_reasoner.getTableau().isSatisfiable(true,false,Collections.singleton(Atom.create(Inequality.INSTANCE,individual1,individual2)),null,null,null,null,new ReasoningTaskDescription(true,"is {0} same as {1}",individual1,individual2)));
}
public void computeSameAsEquivalenceClasses(ReasonerProgressMonitor progressMonitor) {
if (!m_individualToPossibleEquivalenceClass.isEmpty()) {
int steps=m_individualToPossibleEquivalenceClass.keySet().size();
if (steps>0 && progressMonitor!=null)
progressMonitor.reasonerTaskStarted("Precompute same individuals");
while (!m_individualToPossibleEquivalenceClass.isEmpty()) {
Set<Individual> equivalenceClass=m_individualToPossibleEquivalenceClass.keySet().iterator().next();
getSameAsIndividuals(equivalenceClass.iterator().next());
if (progressMonitor!=null)
progressMonitor.reasonerTaskProgressChanged(steps-m_individualToPossibleEquivalenceClass.keySet().size(), steps);
}
if (progressMonitor!=null)
progressMonitor.reasonerTaskStopped();
}
}
protected boolean isInstance(Individual individual,AtomicConcept atomicConcept) {
boolean result = !m_reasoner.getTableau().isSatisfiable(true,false,null,Collections.singleton(Atom.create(atomicConcept,individual)),null,null,null,ReasoningTaskDescription.isInstanceOf(atomicConcept,individual));
if (m_tableauMonitor!=null) {
if (result)
m_tableauMonitor.possibleInstanceIsInstance();
else
m_tableauMonitor.possibleInstanceIsNotInstance();
}
return result;
}
protected boolean isRoleInstance(Role role, Individual individual1, Individual individual2) {
OWLDataFactory factory=m_reasoner.getDataFactory();
AtomicRole atomicRole;
if (role instanceof InverseRole) {
Individual tmp=individual1;
individual1=individual2;
individual2=tmp;
atomicRole=((InverseRole)role).getInverseOf();
}
else
atomicRole=(AtomicRole)role;
OWLObjectProperty property=factory.getOWLObjectProperty(IRI.create(atomicRole.getIRI()));
OWLNamedIndividual namedIndividual1=factory.getOWLNamedIndividual(IRI.create(individual1.getIRI()));
OWLNamedIndividual namedIndividual2=factory.getOWLNamedIndividual(IRI.create(individual2.getIRI()));
OWLClass pseudoNominal=factory.getOWLClass(IRI.create("internal:pseudo-nominal"));
OWLClassExpression allNotPseudoNominal=factory.getOWLObjectAllValuesFrom(property,pseudoNominal.getObjectComplementOf());
OWLAxiom allNotPseudoNominalAssertion=factory.getOWLClassAssertionAxiom(allNotPseudoNominal,namedIndividual1);
OWLAxiom pseudoNominalAssertion=factory.getOWLClassAssertionAxiom(pseudoNominal,namedIndividual2);
Tableau tableau=m_reasoner.getTableau(allNotPseudoNominalAssertion,pseudoNominalAssertion);
boolean result=!tableau.isSatisfiable(true,true,null,null,null,null,null,new ReasoningTaskDescription(true,"is {0} connected to {1} via {2}",individual1,individual2,atomicRole));
if (m_tableauMonitor!=null) {
if (result)
m_tableauMonitor.possibleInstanceIsInstance();
else
m_tableauMonitor.possibleInstanceIsNotInstance();
}
return result;
}
protected static boolean isResultRelevantIndividual(Individual individual) {
return !individual.isAnonymous() && !Prefixes.isInternalIRI(individual.getIRI());
}
public boolean realizationCompleted() {
return m_realizationCompleted;
}
public boolean objectPropertyRealizationCompleted() {
return m_roleRealizationCompleted;
}
public boolean sameAsIndividualsComputed() {
return m_individualToPossibleEquivalenceClass.isEmpty();
}
public boolean areClassesInitialised() {
return m_classesInitialised;
}
public boolean arePropertiesInitialised() {
return m_propertiesInitialised;
}
public int getCurrentIndividualIndex() {
return m_currentIndividualIndex;
}
public Map<Individual, Node> getNodesForIndividuals() {
return m_nodesForIndividuals;
}
}