Package org.semanticweb.HermiT.tableau

Source Code of org.semanticweb.HermiT.tableau.Tableau

/* 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.tableau;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.semanticweb.HermiT.existentials.ExistentialExpansionStrategy;
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.ConstantEnumeration;
import org.semanticweb.HermiT.model.DLClause;
import org.semanticweb.HermiT.model.DLOntology;
import org.semanticweb.HermiT.model.DLPredicate;
import org.semanticweb.HermiT.model.DescriptionGraph;
import org.semanticweb.HermiT.model.Equality;
import org.semanticweb.HermiT.model.ExistentialConcept;
import org.semanticweb.HermiT.model.Individual;
import org.semanticweb.HermiT.model.Inequality;
import org.semanticweb.HermiT.model.LiteralConcept;
import org.semanticweb.HermiT.model.NegatedAtomicRole;
import org.semanticweb.HermiT.model.Term;
import org.semanticweb.HermiT.monitor.TableauMonitor;
import org.semanticweb.HermiT.tableau.Node.NodeState;

/**
* This class coordinates the main tableau expansion for a given DLOntology
* (a normalized and clausified ontology). It represents the state of a run
* on a set of clauses and coordinates the extension of the ABox and also the
* retraction of facts when backtracking. Before starting the expansion,
* the given clauses are (for better performance) preprocessed via the
* HyperresolutionManager into a compiled and executable form.
*/
public final class Tableau implements Serializable {
    private static final long serialVersionUID=-28982363158925221L;

    protected final InterruptFlag m_interruptFlag;
    protected final Map<String,Object> m_parameters;
    protected final TableauMonitor m_tableauMonitor;
    protected final ExistentialExpansionStrategy m_existentialExpansionStrategy;
    protected final DLOntology m_permanentDLOntology;
    protected DLOntology m_additionalDLOntology;
    protected final DependencySetFactory m_dependencySetFactory;
    protected final ExtensionManager m_extensionManager;
    protected final ClashManager m_clashManager;
    protected final HyperresolutionManager m_permanentHyperresolutionManager;
    protected HyperresolutionManager m_additionalHyperresolutionManager;
    protected final MergingManager m_mergingManager;
    protected final ExistentialExpansionManager m_existentialExpasionManager;
    protected final NominalIntroductionManager m_nominalIntroductionManager;
    protected final DescriptionGraphManager m_descriptionGraphManager;
    protected final DatatypeManager m_datatypeManager;
    protected final List<List<ExistentialConcept>> m_existentialConceptsBuffers;
    protected final boolean m_useDisjunctionLearning;
    protected final boolean m_hasDescriptionGraphs;
    protected BranchingPoint[] m_branchingPoints;
    protected int m_currentBranchingPoint;
    protected int m_nonbacktrackableBranchingPoint;
    protected boolean m_isCurrentModelDeterministic;
    protected boolean m_needsThingExtension;
    protected boolean m_needsNamedExtension;
    protected boolean m_checkDatatypes;
    protected boolean m_checkUnknownDatatypeRestrictions;
    protected int m_allocatedNodes;
    protected int m_numberOfNodesInTableau;
    protected int m_numberOfMergedOrPrunedNodes;
    protected int m_numberOfNodeCreations;
    protected Node m_firstFreeNode;
    protected Node m_firstTableauNode;
    protected Node m_lastTableauNode;
    protected Node m_lastMergedOrPrunedNode;
    protected GroundDisjunction m_firstGroundDisjunction;
    protected GroundDisjunction m_firstUnprocessedGroundDisjunction;

    public Tableau(InterruptFlag interruptFlag,TableauMonitor tableauMonitor,ExistentialExpansionStrategy existentialsExpansionStrategy,boolean useDisjunctionLearning,DLOntology permanentDLOntology,DLOntology additionalDLOntology,Map<String,Object> parameters) {
        if (additionalDLOntology!=null && !additionalDLOntology.getAllDescriptionGraphs().isEmpty())
            throw new IllegalArgumentException("Additional ontology cannot contain description graphs.");
        m_interruptFlag=interruptFlag;
        m_interruptFlag.startTask();
        try {
            m_parameters=parameters;
            m_tableauMonitor=tableauMonitor;
            m_existentialExpansionStrategy=existentialsExpansionStrategy;
            m_permanentDLOntology=permanentDLOntology;
            m_additionalDLOntology=additionalDLOntology;
            m_dependencySetFactory=new DependencySetFactory();
            m_extensionManager=new ExtensionManager(this);
            m_clashManager=new ClashManager(this);
            m_permanentHyperresolutionManager=new HyperresolutionManager(this,m_permanentDLOntology.getDLClauses());
            if (m_additionalDLOntology!=null)
                m_additionalHyperresolutionManager=new HyperresolutionManager(this,m_additionalDLOntology.getDLClauses());
            else
                m_additionalHyperresolutionManager=null;
            m_mergingManager=new MergingManager(this);
            m_existentialExpasionManager=new ExistentialExpansionManager(this);
            m_nominalIntroductionManager=new NominalIntroductionManager(this);
            m_descriptionGraphManager=new DescriptionGraphManager(this);
            m_datatypeManager=new DatatypeManager(this);
            m_existentialExpansionStrategy.initialize(this);
            m_existentialConceptsBuffers=new ArrayList<List<ExistentialConcept>>();
            m_useDisjunctionLearning=useDisjunctionLearning;
            m_hasDescriptionGraphs=!m_permanentDLOntology.getAllDescriptionGraphs().isEmpty();
            m_branchingPoints=new BranchingPoint[2];
            m_currentBranchingPoint=-1;
            m_nonbacktrackableBranchingPoint=-1;
            updateFlagsDependentOnAdditionalOntology();
            if (m_tableauMonitor!=null)
                m_tableauMonitor.setTableau(this);
        }
        finally {
            m_interruptFlag.endTask();
        }
    }
    public InterruptFlag getInterruptFlag() {
        return m_interruptFlag;
    }
    public DLOntology getPermanentDLOntology() {
        return m_permanentDLOntology;
    }
    public DLOntology getAdditionalDLOntology() {
        return m_additionalDLOntology;
    }
    public Map<String,Object> getParameters() {
        return m_parameters;
    }
    public TableauMonitor getTableauMonitor() {
        return m_tableauMonitor;
    }
    public ExistentialExpansionStrategy getExistentialsExpansionStrategy() {
        return m_existentialExpansionStrategy;
    }
    public boolean isDeterministic() {
        return m_permanentDLOntology.isHorn() && (m_additionalDLOntology==null || m_additionalDLOntology.isHorn()) && m_existentialExpansionStrategy.isDeterministic();
    }
    public DependencySetFactory getDependencySetFactory() {
        return m_dependencySetFactory;
    }
    public ExtensionManager getExtensionManager() {
        return m_extensionManager;
    }
    public HyperresolutionManager getPermanentHyperresolutionManager() {
        return m_permanentHyperresolutionManager;
    }
    public HyperresolutionManager getAdditionalHyperresolutionManager() {
        return m_additionalHyperresolutionManager;
    }
    public MergingManager getMergingManager() {
        return m_mergingManager;
    }
    public ExistentialExpansionManager getExistentialExpansionManager() {
        return m_existentialExpasionManager;
    }
    public NominalIntroductionManager getNominalIntroductionManager() {
        return m_nominalIntroductionManager;
    }
    public DescriptionGraphManager getDescriptionGraphManager() {
        return m_descriptionGraphManager;
    }
    public void clear() {
        m_allocatedNodes=0;
        m_numberOfNodesInTableau=0;
        m_numberOfMergedOrPrunedNodes=0;
        m_numberOfNodeCreations=0;
        m_firstFreeNode=null;
        m_firstTableauNode=null;
        m_lastTableauNode=null;
        m_lastMergedOrPrunedNode=null;
        m_firstGroundDisjunction=null;
        m_firstUnprocessedGroundDisjunction=null;
        m_branchingPoints=new BranchingPoint[2];
        m_currentBranchingPoint=-1;
        m_nonbacktrackableBranchingPoint=-1;
        m_dependencySetFactory.clear();
        m_extensionManager.clear();
        m_clashManager.clear();
        m_permanentHyperresolutionManager.clear();
        if (m_additionalHyperresolutionManager!=null)
            m_additionalHyperresolutionManager.clear();
        m_mergingManager.clear();
        m_existentialExpasionManager.clear();
        m_nominalIntroductionManager.clear();
        m_descriptionGraphManager.clear();
        m_isCurrentModelDeterministic=true;
        m_existentialExpansionStrategy.clear();
        m_datatypeManager.clear();
        m_existentialConceptsBuffers.clear();
        if (m_tableauMonitor!=null)
            m_tableauMonitor.tableauCleared();
    }
    public boolean supportsAdditionalDLOntology(DLOntology additionalDLOntology) {
        boolean hasInverseRoles=(m_permanentDLOntology.hasInverseRoles() || (m_additionalDLOntology!=null && m_additionalDLOntology.hasInverseRoles()));
        boolean hasNominals=(m_permanentDLOntology.hasNominals() || (m_additionalDLOntology!=null && m_additionalDLOntology.hasNominals()));
        boolean isHorn=(m_permanentDLOntology.isHorn() || (m_additionalDLOntology!=null && m_additionalDLOntology.isHorn()));
        boolean permanentHasBottomObjectProperty=m_permanentDLOntology.containsObjectRole(AtomicRole.BOTTOM_OBJECT_ROLE);
        boolean hasBottomObjectProperty=(permanentHasBottomObjectProperty || (m_additionalDLOntology!=null && m_additionalDLOntology.containsObjectRole(AtomicRole.BOTTOM_OBJECT_ROLE)));
        if (!additionalDLOntology.getAllDescriptionGraphs().isEmpty() || (additionalDLOntology.hasInverseRoles() && !hasInverseRoles) || (additionalDLOntology.hasNominals() && !hasNominals) || (!additionalDLOntology.isHorn() && isHorn) || (hasBottomObjectProperty && !permanentHasBottomObjectProperty))
            return false;
        for (DLClause dlClause : additionalDLOntology.getDLClauses()) {
            DLClause.ClauseType clauseType=dlClause.getClauseType();
            if (clauseType==DLClause.ClauseType.OBJECT_PROPERTY_INCLUSION || clauseType==DLClause.ClauseType.INVERSE_OBJECT_PROPERTY_INCLUSION || dlClause.isFunctionalityAxiom() || dlClause.isInverseFunctionalityAxiom())
                return false;
        }
        return true;
    }
    public void setAdditionalDLOntology(DLOntology additionalDLOntology) {
        if (!supportsAdditionalDLOntology(additionalDLOntology))
            throw new IllegalArgumentException("Additional DL-ontology contains features that are incompatible with this tableau.");
        m_additionalDLOntology=additionalDLOntology;
        m_additionalHyperresolutionManager=new HyperresolutionManager(this,m_additionalDLOntology.getDLClauses());
        m_existentialExpansionStrategy.additionalDLOntologySet(m_additionalDLOntology);
        m_datatypeManager.additionalDLOntologySet(m_additionalDLOntology);
        updateFlagsDependentOnAdditionalOntology();
    }
    public void clearAdditionalDLOntology() {
        m_additionalDLOntology=null;
        m_additionalHyperresolutionManager=null;
        m_existentialExpansionStrategy.additionalDLOntologyCleared();
        m_datatypeManager.additionalDLOntologyCleared();
        updateFlagsDependentOnAdditionalOntology();
    }
    protected void updateFlagsDependentOnAdditionalOntology() {
        m_needsThingExtension=m_permanentHyperresolutionManager.m_tupleConsumersByDeltaPredicate.containsKey(AtomicConcept.THING);
        m_needsNamedExtension=m_permanentHyperresolutionManager.m_tupleConsumersByDeltaPredicate.containsKey(AtomicConcept.INTERNAL_NAMED);
        m_checkDatatypes=m_permanentDLOntology.hasDatatypes();
        m_checkUnknownDatatypeRestrictions=m_permanentDLOntology.hasUnknownDatatypeRestrictions();
        if (m_additionalHyperresolutionManager!=null) {
            m_needsThingExtension|=m_additionalHyperresolutionManager.m_tupleConsumersByDeltaPredicate.containsKey(AtomicConcept.THING);
            m_needsNamedExtension|=m_additionalHyperresolutionManager.m_tupleConsumersByDeltaPredicate.containsKey(AtomicConcept.INTERNAL_NAMED);
        }
        if (m_additionalDLOntology!=null) {
            m_checkDatatypes|=m_additionalDLOntology.hasDatatypes();
            m_checkUnknownDatatypeRestrictions|=m_additionalDLOntology.hasUnknownDatatypeRestrictions();
        }
    }
    public boolean isSatisfiable(boolean loadAdditionalABox,Set<Atom> perTestPositiveFactsNoDependency,Set<Atom> perTestNegativeFactsNoDependency,Set<Atom> perTestPositiveFactsDummyDependency,Set<Atom> perTestNegativeFactsDummyDependency,Map<Individual,Node> nodesForIndividuals,ReasoningTaskDescription reasoningTaskDescription) {
        boolean loadPermanentABox=m_permanentDLOntology.hasNominals() || (m_additionalDLOntology!=null && m_additionalDLOntology.hasNominals());
        return isSatisfiable(loadPermanentABox,loadAdditionalABox,perTestPositiveFactsNoDependency,perTestNegativeFactsNoDependency,perTestPositiveFactsDummyDependency,perTestNegativeFactsDummyDependency,nodesForIndividuals,reasoningTaskDescription);
    }
    public boolean isSatisfiable(boolean loadPermanentABox,boolean loadAdditionalABox,Set<Atom> perTestPositiveFactsNoDependency,Set<Atom> perTestNegativeFactsNoDependency,Set<Atom> perTestPositiveFactsDummyDependency,Set<Atom> perTestNegativeFactsDummyDependency,Map<Individual,Node> nodesForIndividuals,ReasoningTaskDescription reasoningTaskDescription) {
        if (m_tableauMonitor!=null)
            m_tableauMonitor.isSatisfiableStarted(reasoningTaskDescription);
        clear();
        Map<Term,Node> termsToNodes=new HashMap<Term,Node>();
        if (loadPermanentABox) {
            for (Atom atom : m_permanentDLOntology.getPositiveFacts())
                loadPositiveFact(termsToNodes,atom,m_dependencySetFactory.emptySet());
            for (Atom atom : m_permanentDLOntology.getNegativeFacts())
                loadNegativeFact(termsToNodes,atom,m_dependencySetFactory.emptySet());
        }
        if (loadAdditionalABox && m_additionalDLOntology!=null) {
            for (Atom atom : m_additionalDLOntology.getPositiveFacts())
                loadPositiveFact(termsToNodes,atom,m_dependencySetFactory.emptySet());
            for (Atom atom : m_additionalDLOntology.getNegativeFacts())
                loadNegativeFact(termsToNodes,atom,m_dependencySetFactory.emptySet());
        }
        if (perTestPositiveFactsNoDependency!=null && !perTestPositiveFactsNoDependency.isEmpty())
            for (Atom atom : perTestPositiveFactsNoDependency)
                loadPositiveFact(termsToNodes,atom,m_dependencySetFactory.emptySet());
        if (perTestNegativeFactsNoDependency!=null && !perTestNegativeFactsNoDependency.isEmpty())
            for (Atom atom : perTestNegativeFactsNoDependency)
                loadNegativeFact(termsToNodes,atom,m_dependencySetFactory.emptySet());
        if ((perTestPositiveFactsDummyDependency!=null && !perTestPositiveFactsDummyDependency.isEmpty()) || (perTestNegativeFactsDummyDependency!=null && !perTestNegativeFactsDummyDependency.isEmpty())) {
            m_branchingPoints[0]=new BranchingPoint(this);
            m_currentBranchingPoint++;
            m_nonbacktrackableBranchingPoint=m_currentBranchingPoint;
            DependencySet dependencySet=m_dependencySetFactory.addBranchingPoint(m_dependencySetFactory.emptySet(),m_currentBranchingPoint);
            if (perTestPositiveFactsDummyDependency!=null && !perTestPositiveFactsDummyDependency.isEmpty())
                for (Atom atom : perTestPositiveFactsDummyDependency)
                    loadPositiveFact(termsToNodes,atom,dependencySet);
            if (perTestNegativeFactsDummyDependency!=null && !perTestNegativeFactsDummyDependency.isEmpty())
                for (Atom atom : perTestNegativeFactsDummyDependency)
                    loadNegativeFact(termsToNodes,atom,dependencySet);
        }
        if (nodesForIndividuals!=null)
            for (Map.Entry<Individual,Node> entry : nodesForIndividuals.entrySet()) {
                if (termsToNodes.get(entry.getValue())==null) {
                    Atom topAssertion=Atom.create(AtomicConcept.THING, entry.getKey());
                    loadPositiveFact(termsToNodes,topAssertion,m_dependencySetFactory.emptySet());
                }
                entry.setValue(termsToNodes.get(entry.getKey()));
            }
        // Ensure that at least one individual exists.
        if (m_firstTableauNode==null)
            createNewNINode(m_dependencySetFactory.emptySet());
        boolean result=runCalculus();
        if (m_tableauMonitor!=null)
            m_tableauMonitor.isSatisfiableFinished(reasoningTaskDescription,result);
        return result;
    }
    protected void loadPositiveFact(Map<Term,Node> termsToNodes,Atom atom,DependencySet dependencySet) {
        DLPredicate dlPredicate=atom.getDLPredicate();
        if (dlPredicate instanceof LiteralConcept)
            m_extensionManager.addConceptAssertion((LiteralConcept)dlPredicate,getNodeForTerm(termsToNodes,atom.getArgument(0),dependencySet),dependencySet,true);
        else if (dlPredicate instanceof AtomicRole || Equality.INSTANCE.equals(dlPredicate) || Inequality.INSTANCE.equals(dlPredicate))
            m_extensionManager.addAssertion(dlPredicate,getNodeForTerm(termsToNodes,atom.getArgument(0),dependencySet),getNodeForTerm(termsToNodes,atom.getArgument(1),dependencySet),dependencySet,true);
        else if (dlPredicate instanceof DescriptionGraph) {
            DescriptionGraph descriptionGraph=(DescriptionGraph)dlPredicate;
            Object[] tuple=new Object[descriptionGraph.getArity()+1];
            tuple[0]=descriptionGraph;
            for (int argumentIndex=0;argumentIndex<descriptionGraph.getArity();argumentIndex++)
                tuple[argumentIndex+1]=getNodeForTerm(termsToNodes,atom.getArgument(argumentIndex),dependencySet);
            m_extensionManager.addTuple(tuple,dependencySet,true);
        }
        else
            throw new IllegalArgumentException("Unsupported type of positive ground atom.");
    }
    protected void loadNegativeFact(Map<Term,Node> termsToNodes,Atom atom,DependencySet dependencySet) {
        DLPredicate dlPredicate=atom.getDLPredicate();
        if (dlPredicate instanceof LiteralConcept)
            m_extensionManager.addConceptAssertion(((LiteralConcept)dlPredicate).getNegation(),getNodeForTerm(termsToNodes,atom.getArgument(0),dependencySet),dependencySet,true);
        else if (dlPredicate instanceof AtomicRole) {
            Object[] ternaryTuple=m_extensionManager.m_ternaryAuxiliaryTupleAdd;
            ternaryTuple[0]=NegatedAtomicRole.create((AtomicRole)dlPredicate);
            ternaryTuple[1]=getNodeForTerm(termsToNodes,atom.getArgument(0),dependencySet);
            ternaryTuple[2]=getNodeForTerm(termsToNodes,atom.getArgument(1),dependencySet);
            m_extensionManager.addTuple(ternaryTuple,dependencySet,true);
        }
        else if (Equality.INSTANCE.equals(dlPredicate))
            m_extensionManager.addAssertion(Inequality.INSTANCE,getNodeForTerm(termsToNodes,atom.getArgument(0),dependencySet),getNodeForTerm(termsToNodes,atom.getArgument(1),dependencySet),dependencySet,true);
        else if (Inequality.INSTANCE.equals(dlPredicate))
            m_extensionManager.addAssertion(Equality.INSTANCE,getNodeForTerm(termsToNodes,atom.getArgument(0),dependencySet),getNodeForTerm(termsToNodes,atom.getArgument(1),dependencySet),dependencySet,true);
        else
            throw new IllegalArgumentException("Unsupported type of negative ground atom.");
    }
    protected Node getNodeForTerm(Map<Term,Node> termsToNodes,Term term,DependencySet dependencySet) {
        Node node=termsToNodes.get(term);
        if (node==null) {
            if (term instanceof Individual) {
                Individual individual=(Individual)term;
                if (individual.isAnonymous())
                    node=createNewNINode(dependencySet);
                else
                    node=createNewNamedNode(dependencySet);
            }
            else {
                Constant constant=(Constant)term;
                node=createNewRootConstantNode(dependencySet);
                // Anonymous constant values are not assigned a particular value.
                // See the hack in OWLClausification for an explanation.
                if (!constant.isAnonymous())
                    m_extensionManager.addAssertion(ConstantEnumeration.create(new Constant[] { constant }),node,dependencySet,true);
            }
            termsToNodes.put(term,node);
        }
        return node.getCanonicalNode();
    }
    protected boolean runCalculus() {
        m_interruptFlag.startTask();
        try {
            boolean existentialsAreExact=m_existentialExpansionStrategy.isExact();
            if (m_tableauMonitor!=null)
                m_tableauMonitor.saturateStarted();
            boolean hasMoreWork=true;
            while (hasMoreWork) {
                if (m_tableauMonitor!=null)
                    m_tableauMonitor.iterationStarted();
                hasMoreWork=doIteration();
                if (m_tableauMonitor!=null)
                    m_tableauMonitor.iterationFinished();
                if (!existentialsAreExact && !hasMoreWork && !m_extensionManager.containsClash()) {
                    // no more work to do, but since we use a blocking strategy that does not necessarily
                    // establish only valid blocks (existentialsAreExact == false), we tell the blocking
                    // strategy to go through the nodes and check whether all blocks are valid and if not,
                    // continue with the expansion
                    if (m_tableauMonitor!=null)
                        m_tableauMonitor.iterationStarted();
                    hasMoreWork=m_existentialExpansionStrategy.expandExistentials(true); // returns true if some blocks were invalid
                    if (m_tableauMonitor!=null)
                        m_tableauMonitor.iterationFinished();
                }
            }
            if (m_tableauMonitor!=null)
                m_tableauMonitor.saturateFinished(!m_extensionManager.containsClash());
            if (!m_extensionManager.containsClash()) {
                m_existentialExpansionStrategy.modelFound();
                return true;
            }
            else
                return false;
        }
        finally {
            m_interruptFlag.endTask();
        }
    }
    protected boolean doIteration() {
        if (!m_extensionManager.containsClash()) {
            m_nominalIntroductionManager.processAnnotatedEqualities();
            boolean hasChange=false;
            while (m_extensionManager.propagateDeltaNew() && !m_extensionManager.containsClash()) {
                if (m_hasDescriptionGraphs && !m_extensionManager.containsClash())
                    m_descriptionGraphManager.checkGraphConstraints();
                if (!m_extensionManager.containsClash())
                    m_permanentHyperresolutionManager.applyDLClauses();
                if (m_additionalHyperresolutionManager!=null && !m_extensionManager.containsClash())
                    m_additionalHyperresolutionManager.applyDLClauses();
                if (m_checkUnknownDatatypeRestrictions && !m_extensionManager.containsClash())
                    m_datatypeManager.applyUnknownDatatypeRestrictionSemantics();
                if (m_checkDatatypes && !m_extensionManager.containsClash())
                    m_datatypeManager.checkDatatypeConstraints();
                if (!m_extensionManager.containsClash())
                    m_nominalIntroductionManager.processAnnotatedEqualities();
                hasChange=true;
            }
            if (hasChange)
                return true;
        }
        if (!m_extensionManager.containsClash())
            if (m_existentialExpansionStrategy.expandExistentials(false))
                return true;
        if (!m_extensionManager.containsClash()) {
            while (m_firstUnprocessedGroundDisjunction!=null) {
                GroundDisjunction groundDisjunction=m_firstUnprocessedGroundDisjunction;
                if (m_tableauMonitor!=null)
                    m_tableauMonitor.processGroundDisjunctionStarted(groundDisjunction);
                m_firstUnprocessedGroundDisjunction=groundDisjunction.m_previousGroundDisjunction;
                if (!groundDisjunction.isPruned() && !groundDisjunction.isSatisfied(this)) {
                    int[] sortedDisjunctIndexes=groundDisjunction.getGroundDisjunctionHeader().getSortedDisjunctIndexes();
                    DependencySet dependencySet=groundDisjunction.getDependencySet();
                    if (groundDisjunction.getNumberOfDisjuncts()>1) {
                        BranchingPoint branchingPoint=new DisjunctionBranchingPoint(this,groundDisjunction,sortedDisjunctIndexes);
                        pushBranchingPoint(branchingPoint);
                        dependencySet=m_dependencySetFactory.addBranchingPoint(dependencySet,branchingPoint.getLevel());
                    }
                    if (m_tableauMonitor!=null)
                        m_tableauMonitor.disjunctProcessingStarted(groundDisjunction,sortedDisjunctIndexes[0]);
                    groundDisjunction.addDisjunctToTableau(this,sortedDisjunctIndexes[0],dependencySet);
                    if (m_tableauMonitor!=null) {
                        m_tableauMonitor.disjunctProcessingFinished(groundDisjunction,sortedDisjunctIndexes[0]);
                        m_tableauMonitor.processGroundDisjunctionFinished(groundDisjunction);
                    }
                    return true;
                }
                else {
                    if (m_tableauMonitor!=null)
                        m_tableauMonitor.groundDisjunctionSatisfied(groundDisjunction);
                }
                m_interruptFlag.checkInterrupt();
            }
        }
        if (m_extensionManager.containsClash()) {
            DependencySet clashDependencySet=m_extensionManager.getClashDependencySet();
            int newCurrentBranchingPoint=clashDependencySet.getMaximumBranchingPoint();
            if (newCurrentBranchingPoint<=m_nonbacktrackableBranchingPoint)
                return false;
            backtrackTo(newCurrentBranchingPoint);
            BranchingPoint branchingPoint=getCurrentBranchingPoint();
            if (m_tableauMonitor!=null)
                m_tableauMonitor.startNextBranchingPointStarted(branchingPoint);
            branchingPoint.startNextChoice(this,clashDependencySet);
            if (m_tableauMonitor!=null)
                m_tableauMonitor.startNextBranchingPointFinished(branchingPoint);
            m_dependencySetFactory.removeUnusedSets();
            return true;
        }
        return false;
    }
    public boolean isCurrentModelDeterministic() {
        return m_isCurrentModelDeterministic;
    }
    public int getCurrentBranchingPointLevel() {
        return m_currentBranchingPoint;
    }
    public BranchingPoint getCurrentBranchingPoint() {
        return m_branchingPoints[m_currentBranchingPoint];
    }
    public void addGroundDisjunction(GroundDisjunction groundDisjunction) {
        groundDisjunction.m_nextGroundDisjunction=m_firstGroundDisjunction;
        groundDisjunction.m_previousGroundDisjunction=null;
        if (m_firstGroundDisjunction!=null)
            m_firstGroundDisjunction.m_previousGroundDisjunction=groundDisjunction;
        m_firstGroundDisjunction=groundDisjunction;
        if (m_firstUnprocessedGroundDisjunction==null)
            m_firstUnprocessedGroundDisjunction=groundDisjunction;
        if (m_tableauMonitor!=null)
            m_tableauMonitor.groundDisjunctionDerived(groundDisjunction);
    }
    public GroundDisjunction getFirstUnprocessedGroundDisjunction() {
        return m_firstUnprocessedGroundDisjunction;
    }
    /**
     * Add a branching point in case we need to backtrack to this state.
     *
     * @param branchingPoint
     */
    public void pushBranchingPoint(BranchingPoint branchingPoint) {
        assert m_currentBranchingPoint+1==branchingPoint.m_level;
        if (m_tableauMonitor!=null)
            m_tableauMonitor.pushBranchingPointStarted(branchingPoint);
        m_currentBranchingPoint++;
        if (m_currentBranchingPoint>=m_branchingPoints.length) {
            BranchingPoint[] newBranchingPoints=new BranchingPoint[m_currentBranchingPoint*3/2];
            System.arraycopy(m_branchingPoints,0,newBranchingPoints,0,m_branchingPoints.length);
            m_branchingPoints=newBranchingPoints;
        }
        m_branchingPoints[m_currentBranchingPoint]=branchingPoint;
        m_extensionManager.branchingPointPushed();
        m_existentialExpasionManager.branchingPointPushed();
        m_existentialExpansionStrategy.branchingPointPushed();
        m_nominalIntroductionManager.branchingPointPushed();
        m_isCurrentModelDeterministic=false;
        if (m_tableauMonitor!=null)
            m_tableauMonitor.pushBranchingPointFinished(branchingPoint);
    }
    /**
     * Backtrack to a certain branching point in the list of branching points that have been set during the run.
     *
     * @param newCurrentBrancingPoint
     */
    protected void backtrackTo(int newCurrentBrancingPoint) {
        BranchingPoint branchingPoint=m_branchingPoints[newCurrentBrancingPoint];
        if (m_tableauMonitor!=null)
            m_tableauMonitor.backtrackToStarted(branchingPoint);
        // backtrack the list of branching points
        for (int index=newCurrentBrancingPoint+1;index<=m_currentBranchingPoint;index++)
            m_branchingPoints[index]=null;
        m_currentBranchingPoint=newCurrentBrancingPoint;
        // backtrack processed ground disjunctions
        m_firstUnprocessedGroundDisjunction=branchingPoint.m_firstUnprocessedGroundDisjunction;
        // backtrack added ground disjunctions
        GroundDisjunction firstGroundDisjunctionShouldBe=branchingPoint.m_firstGroundDisjunction;
        while (m_firstGroundDisjunction!=firstGroundDisjunctionShouldBe) {
            m_firstGroundDisjunction.destroy(this);
            m_firstGroundDisjunction=m_firstGroundDisjunction.m_nextGroundDisjunction;
        }
        if (m_firstGroundDisjunction!=null)
            m_firstGroundDisjunction.m_previousGroundDisjunction=null;
        // backtrack existentials
        m_existentialExpansionStrategy.backtrack();
        m_existentialExpasionManager.backtrack();
        // backtrack nominal introduction
        m_nominalIntroductionManager.backtrack();
        // backtrack extensions
        m_extensionManager.backtrack();
        // backtrack node merges/prunes
        Node lastMergedOrPrunedNodeShouldBe=branchingPoint.m_lastMergedOrPrunedNode;
        while (m_lastMergedOrPrunedNode!=lastMergedOrPrunedNodeShouldBe)
            backtrackLastMergedOrPrunedNode();
        // backtrack node change list
        Node lastTableauNodeShouldBe=branchingPoint.m_lastTableauNode;
        while (lastTableauNodeShouldBe!=m_lastTableauNode)
            destroyLastTableauNode();
        // finish
        m_extensionManager.clearClash();
        if (m_tableauMonitor!=null)
            m_tableauMonitor.backtrackToFinished(branchingPoint);
    }
    /**
     * Create a new node that represents an individual named in the input ontology (thus, keys have to be applied to it)
     *
     * @param dependencySet
     *            the dependency set for the node
     * @return the created node
     */
    public Node createNewNamedNode(DependencySet dependencySet) {
        return createNewNodeRaw(dependencySet,null,NodeType.NAMED_NODE,0);
    }
    /**
     * Create a new node that represents a nominal, but one that is not named in the input ontology (thus, keys are not applicable)
     *
     * @param dependencySet
     *            the dependency set for the node
     * @return the created node
     */
    public Node createNewNINode(DependencySet dependencySet) {
        return createNewNodeRaw(dependencySet,null,NodeType.NI_NODE,0);
    }
    /**
     * Create a new tree node.
     *
     * @param dependencySet
     *            the dependency set for the node
     * @param parent
     *            the parent of the node that is to be created
     * @return the created node
     */
    public Node createNewTreeNode(DependencySet dependencySet,Node parent) {
        return createNewNodeRaw(dependencySet,parent,NodeType.TREE_NODE,parent.getTreeDepth()+1);
    }
    /**
     * Create a new concrete node for datatypes.
     *
     * @param dependencySet
     *            the dependency set for the node
     * @param parent
     *            the parent of the node that is to be created
     * @return the created node
     */
    public Node createNewConcreteNode(DependencySet dependencySet,Node parent) {
        return createNewNodeRaw(dependencySet,parent,NodeType.CONCRETE_NODE,parent.getTreeDepth()+1);
    }
    /**
     * Create a new root constant node for datatypes.
     *
     * @param dependencySet
     *            the dependency set for the node
     * @return the created node
     */
    public Node createNewRootConstantNode(DependencySet dependencySet) {
        return createNewNodeRaw(dependencySet,null,NodeType.ROOT_CONSTANT_NODE,0);
    }
    /**
     * Create a new node graph node for description graphs
     *
     * @param parent
     *            the parent of the node that is to be created (may be null)
     * @param dependencySet
     *            the dependency set for the node
     * @return the created node
     */
    public Node createNewGraphNode(Node parent,DependencySet dependencySet) {
        return createNewNodeRaw(dependencySet,parent,NodeType.GRAPH_NODE,parent==null ? 0 : parent.getTreeDepth());
    }
    protected Node createNewNodeRaw(DependencySet dependencySet,Node parent,NodeType nodeType,int treeDepth) {
        Node node;
        if (m_firstFreeNode==null) {
            node=new Node(this);
            m_allocatedNodes++;
        }
        else {
            node=m_firstFreeNode;
            m_firstFreeNode=m_firstFreeNode.m_nextTableauNode;
        }
        assert node.m_nodeID==-1;
        assert node.m_nodeState==null;
        node.initialize(++m_numberOfNodesInTableau,parent,nodeType,treeDepth);
        m_existentialExpansionStrategy.nodeInitialized(node);
        node.m_previousTableauNode=m_lastTableauNode;
        if (m_lastTableauNode==null)
            m_firstTableauNode=node;
        else
            m_lastTableauNode.m_nextTableauNode=node;
        m_lastTableauNode=node;
        m_existentialExpansionStrategy.nodeStatusChanged(node);
        m_numberOfNodeCreations++;
        if (m_tableauMonitor!=null)
            m_tableauMonitor.nodeCreated(node);
        if (nodeType!=NodeType.CONCRETE_NODE) {
            m_extensionManager.addConceptAssertion(AtomicConcept.THING,node,dependencySet,true);
            if (nodeType==NodeType.NAMED_NODE && m_needsNamedExtension)
                m_extensionManager.addConceptAssertion(AtomicConcept.INTERNAL_NAMED,node,dependencySet,true);
        }
        return node;
    }
    /**
     * Merges node into mergeInto. We assume that concepts and roles have already been copied from node to mergeInto. After the merge node has state NodeState.MERGED.
     *
     * @param node
     *            the node that is to be merged
     * @param mergeInto
     *            the node we merge into
     * @param dependencySet
     */
    public void mergeNode(Node node,Node mergeInto,DependencySet dependencySet) {
        assert node.m_nodeState==Node.NodeState.ACTIVE;
        assert node.m_mergedInto==null;
        assert node.m_mergedIntoDependencySet==null;
        assert node.m_previousMergedOrPrunedNode==null;
        node.m_mergedInto=mergeInto;
        node.m_mergedIntoDependencySet=m_dependencySetFactory.getPermanent(dependencySet);
        m_dependencySetFactory.addUsage(node.m_mergedIntoDependencySet);
        node.m_nodeState=NodeState.MERGED;
        node.m_previousMergedOrPrunedNode=m_lastMergedOrPrunedNode;
        m_lastMergedOrPrunedNode=node;
        m_numberOfMergedOrPrunedNodes++;
        m_existentialExpansionStrategy.nodeStatusChanged(node);
        m_existentialExpansionStrategy.nodesMerged(node,mergeInto);
    }
    public void pruneNode(Node node) {
        assert node.m_nodeState==Node.NodeState.ACTIVE;
        assert node.m_mergedInto==null;
        assert node.m_mergedIntoDependencySet==null;
        assert node.m_previousMergedOrPrunedNode==null;
        node.m_nodeState=NodeState.PRUNED;
        node.m_previousMergedOrPrunedNode=m_lastMergedOrPrunedNode;
        m_lastMergedOrPrunedNode=node;
        m_numberOfMergedOrPrunedNodes++;
        m_existentialExpansionStrategy.nodeStatusChanged(node);
    }
    protected void backtrackLastMergedOrPrunedNode() {
        Node node=m_lastMergedOrPrunedNode;
        assert (node.m_nodeState==Node.NodeState.MERGED && node.m_mergedInto!=null && node.m_mergedInto!=null) || (node.m_nodeState==Node.NodeState.PRUNED && node.m_mergedInto==null && node.m_mergedInto==null);
        Node savedMergedInfo=null;
        if (node.m_nodeState==Node.NodeState.MERGED) {
            m_dependencySetFactory.removeUsage(node.m_mergedIntoDependencySet);
            savedMergedInfo=node.m_mergedInto;
            node.m_mergedInto=null;
            node.m_mergedIntoDependencySet=null;
        }
        node.m_nodeState=Node.NodeState.ACTIVE;
        m_lastMergedOrPrunedNode=node.m_previousMergedOrPrunedNode;
        node.m_previousMergedOrPrunedNode=null;
        m_numberOfMergedOrPrunedNodes--;
        m_existentialExpansionStrategy.nodeStatusChanged(node);
        if (savedMergedInfo!=null)
            m_existentialExpansionStrategy.nodesUnmerged(node,savedMergedInfo);
    }
    protected void destroyLastTableauNode() {
        Node node=m_lastTableauNode;
        assert node.m_nodeState==Node.NodeState.ACTIVE;
        assert node.m_mergedInto==null;
        assert node.m_mergedIntoDependencySet==null;
        assert node.m_previousMergedOrPrunedNode==null;
        m_existentialExpansionStrategy.nodeDestroyed(node);
        if (node.m_previousTableauNode==null)
            m_firstTableauNode=null;
        else
            node.m_previousTableauNode.m_nextTableauNode=null;
        m_lastTableauNode=node.m_previousTableauNode;
        node.destroy();
        node.m_nextTableauNode=m_firstFreeNode;
        m_firstFreeNode=node;
        m_numberOfNodesInTableau--;
        if (m_tableauMonitor!=null)
            m_tableauMonitor.nodeDestroyed(node);
    }
    public int getNumberOfNodeCreations() {
        return m_numberOfNodeCreations;
    }
    public Node getFirstTableauNode() {
        return m_firstTableauNode;
    }
    public Node getLastTableauNode() {
        return m_lastTableauNode;
    }
    public int getNumberOfAllocatedNodes() {
        return m_allocatedNodes;
    }
    public int getNumberOfNodesInTableau() {
        return m_numberOfNodesInTableau;
    }
    public int getNumberOfMergedOrPrunedNodes() {
        return m_numberOfMergedOrPrunedNodes;
    }
    public Node getNode(int nodeID) {
        Node node=m_firstTableauNode;
        while (node!=null) {
            if (node.getNodeID()==nodeID)
                return node;
            node=node.getNextTableauNode();
        }
        return null;
    }
    protected List<ExistentialConcept> getExistentialConceptsBuffer() {
        if (m_existentialConceptsBuffers.isEmpty())
            return new ArrayList<ExistentialConcept>();
        else
            return m_existentialConceptsBuffers.remove(m_existentialConceptsBuffers.size()-1);
    }
    public void putExistentialConceptsBuffer(List<ExistentialConcept> buffer) {
        assert buffer.isEmpty();
        m_existentialConceptsBuffers.add(buffer);
    }
    public void checkTableauList() {
        Node node=m_firstTableauNode;
        int numberOfNodesInTableau=0;
        while (node!=null) {
            if (node.m_previousTableauNode==null) {
                if (m_firstTableauNode!=node)
                    throw new IllegalStateException("First tableau node is pointing wrongly.");
            }
            else {
                if (node.m_previousTableauNode.m_nextTableauNode!=node)
                    throw new IllegalStateException("Previous tableau node is pointing wrongly.");
            }
            if (node.m_nextTableauNode==null) {
                if (m_lastTableauNode!=node)
                    throw new IllegalStateException("Last tableau node is pointing wrongly.");
            }
            else {
                if (node.m_nextTableauNode.m_previousTableauNode!=node)
                    throw new IllegalStateException("Next tableau node is pointing wrongly.");
            }
            numberOfNodesInTableau++;
            node=node.m_nextTableauNode;
        }
        if (numberOfNodesInTableau!=m_numberOfNodesInTableau)
            throw new IllegalStateException("Invalid number of nodes in the tableau.");
    }
}
TOP

Related Classes of org.semanticweb.HermiT.tableau.Tableau

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.