Package org.semanticweb.HermiT.tableau

Source Code of org.semanticweb.HermiT.tableau.DatatypeManager$SmallestEnumerationFirst

/* 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.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

import org.semanticweb.HermiT.Prefixes;
import org.semanticweb.HermiT.datatypes.DatatypeRegistry;
import org.semanticweb.HermiT.datatypes.ValueSpaceSubset;
import org.semanticweb.HermiT.model.ConstantEnumeration;
import org.semanticweb.HermiT.model.DLOntology;
import org.semanticweb.HermiT.model.DataRange;
import org.semanticweb.HermiT.model.DatatypeRestriction;
import org.semanticweb.HermiT.model.Inequality;
import org.semanticweb.HermiT.model.NegationDataRange;
import org.semanticweb.HermiT.monitor.TableauMonitor;

public final class DatatypeManager implements Serializable {
    private static final long serialVersionUID=-5304869484553471737L;

    protected final InterruptFlag m_interruptFlag;
    protected final TableauMonitor m_tableauMonitor;
    protected final ExtensionManager m_extensionManager;
    protected final ExtensionTable.Retrieval m_assertionsDeltaOldRetrieval;
    protected final ExtensionTable.Retrieval m_inequalityDeltaOldRetrieval;
    protected final ExtensionTable.Retrieval m_inequality01Retrieval;
    protected final ExtensionTable.Retrieval m_inequality02Retrieval;
    protected final ExtensionTable.Retrieval m_assertions0Retrieval;
    protected final ExtensionTable.Retrieval m_assertions1Retrieval;
    protected final DConjunction m_conjunction;
    protected final List<DVariable> m_auxiliaryVariableList;
    protected final UnionDependencySet m_unionDependencySet;
    protected final boolean[] m_newVariableAdded;
    protected final Set<DatatypeRestriction> m_unknownDatatypeRestrictionsPermanent;
    protected Set<DatatypeRestriction> m_unknownDatatypeRestrictionsAdditional;

    public DatatypeManager(Tableau tableau) {
        m_interruptFlag=tableau.m_interruptFlag;
        m_tableauMonitor=tableau.m_tableauMonitor;
        m_extensionManager=tableau.m_extensionManager;
        m_assertionsDeltaOldRetrieval=m_extensionManager.getBinaryExtensionTable().createRetrieval(new boolean[] { false,false },ExtensionTable.View.DELTA_OLD);
        // The following retrieval should actually be created such that it has Inequality.INSTANCE as the first binding.
        // We don't do this because of the implementation of the ExtensionTable. Namely, each ExtensionTable keeps
        // only one index for all tuples, and then filters out the assertions that don't fit into the index. As a
        // side effect of such an implementation, this means that each time we go through the entire index for inequalities,
        // which can take up a lot of time. The current solution is more efficient: it goes through the actual delta-old
        // and then filters out inequalities "manually".
        m_inequalityDeltaOldRetrieval=m_extensionManager.getTernaryExtensionTable().createRetrieval(new boolean[] { false,false,false },ExtensionTable.View.DELTA_OLD);
        m_inequality01Retrieval=m_extensionManager.getTernaryExtensionTable().createRetrieval(new boolean[] { true,true,false },ExtensionTable.View.EXTENSION_THIS);
        m_inequality02Retrieval=m_extensionManager.getTernaryExtensionTable().createRetrieval(new boolean[] { true,false,true },ExtensionTable.View.EXTENSION_THIS);
        m_assertions0Retrieval=m_extensionManager.getBinaryExtensionTable().createRetrieval(new boolean[] { true,false },ExtensionTable.View.EXTENSION_THIS);
        m_assertions1Retrieval=m_extensionManager.getBinaryExtensionTable().createRetrieval(new boolean[] { false,true },ExtensionTable.View.EXTENSION_THIS);
        m_conjunction=new DConjunction();
        m_auxiliaryVariableList=new ArrayList<DVariable>();
        m_unionDependencySet=new UnionDependencySet(16);
        m_newVariableAdded=new boolean[1];
        m_unknownDatatypeRestrictionsPermanent=tableau.m_permanentDLOntology.getAllUnknownDatatypeRestrictions();
        if (tableau.m_additionalDLOntology!=null)
            additionalDLOntologySet(tableau.m_additionalDLOntology);
    }
    public void additionalDLOntologySet(DLOntology additionalDLOntology) {
        m_unknownDatatypeRestrictionsAdditional=additionalDLOntology.getAllUnknownDatatypeRestrictions();
    }
    public void additionalDLOntologyCleared() {
        m_unknownDatatypeRestrictionsAdditional=null;
    }
    public void clear() {
        m_assertionsDeltaOldRetrieval.clear();
        m_inequalityDeltaOldRetrieval.clear();
        m_inequality01Retrieval.clear();
        m_inequality02Retrieval.clear();
        m_assertions0Retrieval.clear();
        m_assertions1Retrieval.clear();
        m_conjunction.clear();
        m_auxiliaryVariableList.clear();
        m_unionDependencySet.clearConstituents();
    }
    public void applyUnknownDatatypeRestrictionSemantics() {
        Object[] tupleBuffer=m_assertionsDeltaOldRetrieval.getTupleBuffer();
        m_assertionsDeltaOldRetrieval.open();
        while (!m_extensionManager.containsClash() && !m_assertionsDeltaOldRetrieval.afterLast()) {
            Object dataRangeObject=tupleBuffer[0];
            if (dataRangeObject instanceof DatatypeRestriction) {
                DatatypeRestriction datatypeRestriction=(DatatypeRestriction)dataRangeObject;
                if (m_unknownDatatypeRestrictionsPermanent.contains(datatypeRestriction) || (m_unknownDatatypeRestrictionsAdditional!=null && m_unknownDatatypeRestrictionsAdditional.contains(datatypeRestriction)))
                    generateInequalitiesFor(datatypeRestriction,(Node)tupleBuffer[1],m_assertionsDeltaOldRetrieval.getDependencySet(),NegationDataRange.create(datatypeRestriction));
            }
            else if (dataRangeObject instanceof NegationDataRange) {
                NegationDataRange negationDataRange=(NegationDataRange)dataRangeObject;
                DataRange negatedDataRange=negationDataRange.getNegatedDataRange();
                if (negatedDataRange instanceof DatatypeRestriction) {
                    DatatypeRestriction datatypeRestriction=(DatatypeRestriction)negatedDataRange;
                    if (m_unknownDatatypeRestrictionsPermanent.contains(datatypeRestriction) || (m_unknownDatatypeRestrictionsAdditional!=null && m_unknownDatatypeRestrictionsAdditional.contains(datatypeRestriction)))
                        generateInequalitiesFor(negationDataRange,(Node)tupleBuffer[1],m_assertionsDeltaOldRetrieval.getDependencySet(),datatypeRestriction);
                }
            }
            m_assertionsDeltaOldRetrieval.next();
        }
    }
    protected void generateInequalitiesFor(DataRange dataRange1,Node node1,DependencySet dependencySet1,DataRange dataRange2) {
        m_unionDependencySet.clearConstituents();
        m_unionDependencySet.addConstituent(dependencySet1);
        m_unionDependencySet.addConstituent(null);
        m_assertions0Retrieval.getBindingsBuffer()[0]=dataRange2;
        Object[] tupleBuffer=m_assertions0Retrieval.getTupleBuffer();
        m_assertions0Retrieval.open();
        while (!m_assertions0Retrieval.afterLast()) {
            Node node2=(Node)tupleBuffer[1];
            m_unionDependencySet.m_dependencySets[1]=m_assertions0Retrieval.getDependencySet();
            if (m_tableauMonitor!=null)
                m_tableauMonitor.unknownDatatypeRestrictionDetectionStarted(dataRange1,node1,dataRange2,node2);
            m_extensionManager.addAssertion(Inequality.INSTANCE,node1,node2,m_unionDependencySet,false);
            if (m_tableauMonitor!=null)
                m_tableauMonitor.unknownDatatypeRestrictionDetectionFinished(dataRange1,node1,dataRange2,node2);
            m_assertions0Retrieval.next();
        }
    }
    public void checkDatatypeConstraints() {
        if (m_tableauMonitor!=null)
            m_tableauMonitor.datatypeCheckingStarted();
        m_conjunction.clear();
        Object[] tupleBuffer=m_assertionsDeltaOldRetrieval.getTupleBuffer();
        m_assertionsDeltaOldRetrieval.open();
        while (!m_extensionManager.containsClash() && !m_assertionsDeltaOldRetrieval.afterLast()) {
            if (tupleBuffer[0] instanceof DataRange) {
                // A data range was added in the last saturation step, so we check the D-conjunction hanging off of its node.
                Node node=(Node)tupleBuffer[1];
                DVariable variable=getAndInitializeVariableFor(node,m_newVariableAdded);
                // m_newVariableAdded[0]==false means that 'variable' has already been checked in this iteration.
                if (m_newVariableAdded[0]) {
                    m_conjunction.clearActiveVariables();
                    loadConjunctionFrom(variable);
                    checkConjunctionSatisfiability();
                }
            }
            m_assertionsDeltaOldRetrieval.next();
        }
        tupleBuffer=m_inequalityDeltaOldRetrieval.getTupleBuffer();
        m_inequalityDeltaOldRetrieval.open();
        while (!m_extensionManager.containsClash() && !m_inequalityDeltaOldRetrieval.afterLast()) {
            // This is a part of the hack described in the constructor: m_inequalityDeltaOldRetrieval
            // iterates through the entire extension (for efficiency) and then we need to filter out
            // inequalities ourselves.
            if (Inequality.INSTANCE.equals(tupleBuffer[0])) {
                Node node1=(Node)tupleBuffer[1];
                Node node2=(Node)tupleBuffer[2];
                if (!node1.getNodeType().isAbstract() && !node2.getNodeType().isAbstract()) {
                    m_conjunction.clearActiveVariables();
                    // An inequality between concrete was added in the last saturation step, so we check the D-conjunction hanging off of its node.
                    DVariable variable1=getAndInitializeVariableFor(node1,m_newVariableAdded);
                    // m_newVariableAdded[0]==false means that 'variable1' has already been checked in this iteration.
                    if (m_newVariableAdded[0])
                        loadConjunctionFrom(variable1);
                    DVariable variable2=getAndInitializeVariableFor(node2,m_newVariableAdded);
                    // m_newVariableAdded[0]==false means that 'variable1' has already been checked in this iteration.
                    if (m_newVariableAdded[0])
                        loadConjunctionFrom(variable2);
                    m_conjunction.addInequality(variable1,variable2);
                    checkConjunctionSatisfiability();
                }
            }
            m_inequalityDeltaOldRetrieval.next();
        }
        if (m_tableauMonitor!=null)
            m_tableauMonitor.datatypeCheckingFinished(!m_extensionManager.containsClash());
        m_unionDependencySet.clearConstituents();
        m_conjunction.clear();
        m_auxiliaryVariableList.clear();
    }
    protected void loadConjunctionFrom(DVariable startVariable) {
        m_auxiliaryVariableList.clear();
        m_auxiliaryVariableList.add(startVariable);
        while (!m_extensionManager.containsClash() && !m_auxiliaryVariableList.isEmpty()) {
            DVariable reachedVariable=m_auxiliaryVariableList.remove(m_auxiliaryVariableList.size()-1);
            if (!m_conjunction.m_activeVariables.contains(reachedVariable)) {
                m_conjunction.m_activeVariables.add(reachedVariable);
                // Concrete root nodes are assigned a particular value, so they act as "breakers" in the conjunction:
                // the nodes that are unequal to them can be analyzed independently.
                if (reachedVariable.m_node.getNodeType()!=NodeType.ROOT_CONSTANT_NODE) {
                    // Look for all inequalities where reachedNode occurs in the first position.
                    m_inequality01Retrieval.getBindingsBuffer()[0]=Inequality.INSTANCE;
                    m_inequality01Retrieval.getBindingsBuffer()[1]=reachedVariable.m_node;
                    m_inequality01Retrieval.open();
                    Object[] tupleBuffer=m_inequality01Retrieval.getTupleBuffer();
                    while (!m_extensionManager.containsClash() && !m_inequality01Retrieval.afterLast()) {
                        Node newNode=(Node)tupleBuffer[2];
                        DVariable newVariable=getAndInitializeVariableFor(newNode,m_newVariableAdded);
                        m_auxiliaryVariableList.add(newVariable);
                        m_conjunction.addInequality(reachedVariable,newVariable);
                        m_inequality01Retrieval.next();
                        m_interruptFlag.checkInterrupt();
                    }
                    // Look for all inequalities where reachedNode occurs in the second position.
                    m_inequality02Retrieval.getBindingsBuffer()[0]=Inequality.INSTANCE;
                    m_inequality02Retrieval.getBindingsBuffer()[2]=reachedVariable.m_node;
                    m_inequality02Retrieval.open();
                    tupleBuffer=m_inequality02Retrieval.getTupleBuffer();
                    while (!m_extensionManager.containsClash() && !m_inequality02Retrieval.afterLast()) {
                        Node newNode=(Node)tupleBuffer[1];
                        DVariable newVariable=getAndInitializeVariableFor(newNode,m_newVariableAdded);
                        m_auxiliaryVariableList.add(newVariable);
                        m_conjunction.addInequality(newVariable,reachedVariable);
                        m_inequality02Retrieval.next();
                        m_interruptFlag.checkInterrupt();
                    }
                }
            }
        }
    }
    protected DVariable getAndInitializeVariableFor(Node node,boolean[] newVariableAdded) {
        DVariable variable=m_conjunction.getVariableForEx(node,newVariableAdded);
        if (m_newVariableAdded[0]) {
            m_assertions1Retrieval.getBindingsBuffer()[1]=variable.m_node;
            m_assertions1Retrieval.open();
            Object[] tupleBuffer=m_assertions1Retrieval.getTupleBuffer();
            while (!m_extensionManager.containsClash() && !m_assertions1Retrieval.afterLast()) {
                Object potentialDataRange=tupleBuffer[0];
                if (potentialDataRange instanceof DataRange)
                    addDataRange(variable,(DataRange)potentialDataRange);
                m_assertions1Retrieval.next();
                m_interruptFlag.checkInterrupt();
            }
            if (!m_extensionManager.containsClash())
                normalize(variable);
        }
        return variable;
    }
    protected void addDataRange(DVariable variable,DataRange dataRange) {
        if (dataRange instanceof DatatypeRestriction) {
            DatatypeRestriction datatypeRestriction=(DatatypeRestriction)dataRange;
            if (!m_unknownDatatypeRestrictionsPermanent.contains(datatypeRestriction) && (m_unknownDatatypeRestrictionsAdditional==null || !m_unknownDatatypeRestrictionsAdditional.contains(datatypeRestriction))) {
                variable.m_positiveDatatypeRestrictions.add(datatypeRestriction);
                if (variable.m_mostSpecificRestriction==null)
                    variable.m_mostSpecificRestriction=datatypeRestriction;
                else if (DatatypeRegistry.isDisjointWith(variable.m_mostSpecificRestriction.getDatatypeURI(),datatypeRestriction.getDatatypeURI())) {
                    m_unionDependencySet.clearConstituents();
                    m_unionDependencySet.addConstituent(m_extensionManager.getAssertionDependencySet(variable.m_mostSpecificRestriction,variable.m_node));
                    m_unionDependencySet.addConstituent(m_extensionManager.getAssertionDependencySet(datatypeRestriction,variable.m_node));
                    Object[] tuple1;
                    Object[] tuple2;
                    if (m_tableauMonitor!=null) {
                        tuple1=new Object[] { variable.m_mostSpecificRestriction,variable.m_node };
                        tuple2=new Object[] { datatypeRestriction,variable.m_node };
                        m_tableauMonitor.clashDetectionStarted(tuple1,tuple2);
                    }
                    m_extensionManager.setClash(m_unionDependencySet);
                    if (m_tableauMonitor!=null) {
                        tuple1=new Object[] { variable.m_mostSpecificRestriction,variable.m_node };
                        tuple2=new Object[] { datatypeRestriction,variable.m_node };
                        m_tableauMonitor.clashDetectionFinished(tuple1,tuple2);
                    }
                }
                else if (DatatypeRegistry.isSubsetOf(datatypeRestriction.getDatatypeURI(),variable.m_mostSpecificRestriction.getDatatypeURI()))
                    variable.m_mostSpecificRestriction=datatypeRestriction;
            }
        }
        else if (dataRange instanceof ConstantEnumeration)
            variable.m_positiveConstantEnumerations.add((ConstantEnumeration)dataRange);
        else if (dataRange instanceof NegationDataRange) {
            DataRange negatedDataRange=((NegationDataRange)dataRange).getNegatedDataRange();
            if (negatedDataRange instanceof DatatypeRestriction) {
                DatatypeRestriction datatypeRestriction=(DatatypeRestriction)negatedDataRange;
                if (!m_unknownDatatypeRestrictionsPermanent.contains(datatypeRestriction) && (m_unknownDatatypeRestrictionsAdditional==null || !m_unknownDatatypeRestrictionsAdditional.contains(datatypeRestriction)))
                    variable.m_negativeDatatypeRestrictions.add(datatypeRestriction);
            }
            else if (negatedDataRange instanceof ConstantEnumeration) {
                ConstantEnumeration negatedConstantEnumeration=(ConstantEnumeration)negatedDataRange;
                variable.m_negativeConstantEnumerations.add(negatedConstantEnumeration);
                for (int index=negatedConstantEnumeration.getNumberOfConstants()-1;index>=0;--index)
                    variable.addForbiddenDataValue(negatedConstantEnumeration.getConstant(index).getDataValue());
            }
            else
                throw new IllegalStateException("Internal error: invalid data range.");
        }
        else
            throw new IllegalStateException("Internal error: invalid data range.");
    }
    protected void checkConjunctionSatisfiability() {
        if (!m_extensionManager.containsClash() && !m_conjunction.m_activeVariables.isEmpty()) {
            if (m_tableauMonitor!=null)
                m_tableauMonitor.datatypeConjunctionCheckingStarted(m_conjunction);
            if (m_conjunction.isSymmetricClique()) {
                DVariable representative=m_conjunction.m_activeVariables.get(0);
                if (!m_extensionManager.containsClash() && !representative.hasCardinalityAtLeast(m_conjunction.m_activeVariables.size()))
                    setClashFor(m_conjunction.m_activeVariables);
            }
            else if (!m_extensionManager.containsClash()) {
                eliminateTrivialInequalities();
                eliminateTriviallySatisfiableNodes();
                enumerateValueSpaceSubsets();
                if (!m_extensionManager.containsClash()) {
                    eliminateTriviallySatisfiableNodes();
                    checkAssignments();
                }
            }
            if (m_tableauMonitor!=null)
                m_tableauMonitor.datatypeConjunctionCheckingFinished(m_conjunction,!m_extensionManager.containsClash());
        }
    }
    protected void normalize(DVariable variable) {
        if (!variable.m_positiveConstantEnumerations.isEmpty())
            normalizeAsEnumeration(variable);
        else if (!variable.m_positiveDatatypeRestrictions.isEmpty())
            normalizeAsValueSpaceSubset(variable);
    }
    protected void normalizeAsEnumeration(DVariable variable) {
        variable.m_hasExplicitDataValues=true;
        List<Object> explicitDataValues=variable.m_explicitDataValues;
        List<ConstantEnumeration> positiveConstantEnumerations=variable.m_positiveConstantEnumerations;
        ConstantEnumeration firstDataValueEnumeration=positiveConstantEnumerations.get(0);
        nextValue: for (int index=firstDataValueEnumeration.getNumberOfConstants()-1;index>=0;--index) {
            Object dataValue=firstDataValueEnumeration.getConstant(index).getDataValue();
            if (!explicitDataValues.contains(dataValue) && !variable.m_forbiddenDataValues.contains(dataValue)) {
                for (int enumerationIndex=positiveConstantEnumerations.size()-1;enumerationIndex>=1;--enumerationIndex)
                    if (!containsDataValue(positiveConstantEnumerations.get(enumerationIndex),dataValue))
                        continue nextValue;
                explicitDataValues.add(dataValue);
            }
        }
        variable.m_forbiddenDataValues.clear();
        List<DatatypeRestriction> positiveDatatypeRestrictions=variable.m_positiveDatatypeRestrictions;
        for (int index=positiveDatatypeRestrictions.size()-1;!explicitDataValues.isEmpty() && index>=0;--index) {
            DatatypeRestriction positiveDatatypeRestriction=positiveDatatypeRestrictions.get(index);
            ValueSpaceSubset valueSpaceSubset=DatatypeRegistry.createValueSpaceSubset(positiveDatatypeRestriction);
            eliminateDataValuesUsingValueSpaceSubset(valueSpaceSubset,explicitDataValues,false);
        }
        List<DatatypeRestriction> negativeDatatypeRestrictions=variable.m_negativeDatatypeRestrictions;
        for (int index=negativeDatatypeRestrictions.size()-1;!explicitDataValues.isEmpty() && index>=0;--index) {
            DatatypeRestriction negativeDatatypeRestriction=negativeDatatypeRestrictions.get(index);
            ValueSpaceSubset valueSpaceSubset=DatatypeRegistry.createValueSpaceSubset(negativeDatatypeRestriction);
            eliminateDataValuesUsingValueSpaceSubset(valueSpaceSubset,explicitDataValues,true);
        }
        if (explicitDataValues.isEmpty())
            setClashFor(variable);
    }
    protected boolean containsDataValue(ConstantEnumeration constantEnumeration,Object dataValue) {
        for (int index=constantEnumeration.getNumberOfConstants()-1;index>=0;--index)
            if (constantEnumeration.getConstant(index).getDataValue().equals(dataValue))
                return true;
        return false;
    }
    protected void eliminateDataValuesUsingValueSpaceSubset(ValueSpaceSubset valueSpaceSubset,List<Object> explicitDataValues,boolean eliminateWhenValue) {
        for (int valueIndex=explicitDataValues.size()-1;valueIndex>=0;--valueIndex) {
            Object dataValue=explicitDataValues.get(valueIndex);
            if (valueSpaceSubset.containsDataValue(dataValue)==eliminateWhenValue)
                explicitDataValues.remove(valueIndex);
        }
    }
    protected void normalizeAsValueSpaceSubset(DVariable variable) {
        String mostSpecificDatatypeURI=variable.m_mostSpecificRestriction.getDatatypeURI();
        variable.m_valueSpaceSubset=DatatypeRegistry.createValueSpaceSubset(variable.m_mostSpecificRestriction);
        List<DatatypeRestriction> positiveDatatypeRestrictions=variable.m_positiveDatatypeRestrictions;
        for (int index=positiveDatatypeRestrictions.size()-1;index>=0;--index) {
            DatatypeRestriction datatypeRestriction=positiveDatatypeRestrictions.get(index);
            if (datatypeRestriction!=variable.m_mostSpecificRestriction)
                variable.m_valueSpaceSubset=DatatypeRegistry.conjoinWithDR(variable.m_valueSpaceSubset,datatypeRestriction);
        }
        List<DatatypeRestriction> negativeDatatypeRestrictions=variable.m_negativeDatatypeRestrictions;
        for (int index=negativeDatatypeRestrictions.size()-1;index>=0;--index) {
            DatatypeRestriction datatypeRestriction=negativeDatatypeRestrictions.get(index);
            String datatypeRestrictionDatatypeURI=datatypeRestriction.getDatatypeURI();
            if (!DatatypeRegistry.isDisjointWith(mostSpecificDatatypeURI,datatypeRestrictionDatatypeURI))
                variable.m_valueSpaceSubset=DatatypeRegistry.conjoinWithDRNegation(variable.m_valueSpaceSubset,datatypeRestriction);
        }
        if (!variable.m_valueSpaceSubset.hasCardinalityAtLeast(1)) {
            variable.m_forbiddenDataValues.clear();
            setClashFor(variable);
        }
        else {
            for (int valueIndex=variable.m_forbiddenDataValues.size()-1;valueIndex>=0;--valueIndex) {
                Object forbiddenValue=variable.m_forbiddenDataValues.get(valueIndex);
                if (!variable.m_valueSpaceSubset.containsDataValue(forbiddenValue))
                    variable.m_forbiddenDataValues.remove(valueIndex);
            }
        }
    }
    protected void eliminateTrivialInequalities() {
        for (int index1=m_conjunction.m_activeVariables.size()-1;index1>=0;--index1) {
            DVariable variable1=m_conjunction.m_activeVariables.get(index1);
            if (variable1.m_mostSpecificRestriction!=null) {
                String datatypeURI1=variable1.m_mostSpecificRestriction.getDatatypeURI();
                for (int index2=variable1.m_unequalToDirect.size()-1;index2>=0;--index2) {
                    DVariable variable2=variable1.m_unequalToDirect.get(index2);
                    if (variable2.m_mostSpecificRestriction!=null && DatatypeRegistry.isDisjointWith(datatypeURI1,variable2.m_mostSpecificRestriction.getDatatypeURI())) {
                        variable1.m_unequalTo.remove(variable2);
                        variable1.m_unequalToDirect.remove(variable2);
                        variable2.m_unequalTo.remove(variable1);
                        variable2.m_unequalToDirect.remove(variable1);
                    }
                }
            }
        }
    }
    protected void eliminateTriviallySatisfiableNodes() {
        m_auxiliaryVariableList.clear();
        for (int index=m_conjunction.m_activeVariables.size()-1;index>=0;--index)
            m_auxiliaryVariableList.add(m_conjunction.m_activeVariables.get(index));
        while (!m_auxiliaryVariableList.isEmpty()) {
            DVariable variable=m_auxiliaryVariableList.remove(m_auxiliaryVariableList.size()-1);
            if (variable.hasCardinalityAtLeast(variable.m_unequalTo.size()+1)) {
                for (int index=variable.m_unequalTo.size()-1;index>=0;--index) {
                    DVariable neighborVariable=variable.m_unequalTo.get(index);
                    neighborVariable.m_unequalTo.remove(variable);
                    neighborVariable.m_unequalToDirect.remove(variable);
                    if (!m_auxiliaryVariableList.contains(neighborVariable))
                        m_auxiliaryVariableList.add(neighborVariable);
                }
                variable.clearEqualities();
                m_conjunction.m_activeVariables.remove(variable);
            }
        }
    }
    protected void enumerateValueSpaceSubsets() {
        for (int index=m_conjunction.m_activeVariables.size()-1;!m_extensionManager.containsClash() && index>=0;--index) {
            DVariable variable=m_conjunction.m_activeVariables.get(index);
            if (variable.m_valueSpaceSubset!=null) {
                variable.m_hasExplicitDataValues=true;
                variable.m_valueSpaceSubset.enumerateDataValues(variable.m_explicitDataValues);
                if (!variable.m_forbiddenDataValues.isEmpty()) {
                    for (int valueIndex=variable.m_explicitDataValues.size()-1;valueIndex>=0;--valueIndex) {
                        Object dataValue=variable.m_explicitDataValues.get(valueIndex);
                        if (variable.m_forbiddenDataValues.contains(dataValue))
                            variable.m_explicitDataValues.remove(valueIndex);
                    }
                }
                variable.m_valueSpaceSubset=null;
                variable.m_forbiddenDataValues.clear();
                if (variable.m_explicitDataValues.isEmpty())
                    setClashFor(variable);
            }
        }
    }
    protected void checkAssignments() {
        // This method could be further optimized to check each clique of inequalities separately.
        // It is not expected that this is an important optimization, so we don't to it for the moment.
        // The nodes are sorted so that we get a kind of 'join order' optimization.
        Collections.sort(m_conjunction.m_activeVariables,SmallestEnumerationFirst.INSTANCE);
        if (!findAssignment(0))
            setClashFor(m_conjunction.m_activeVariables);
    }
    protected boolean findAssignment(int nodeIndex) {
        if (nodeIndex==m_conjunction.m_activeVariables.size())
            return true;
        else {
            DVariable variable=m_conjunction.m_activeVariables.get(nodeIndex);
            for (int valueIndex=variable.m_explicitDataValues.size()-1;valueIndex>=0;--valueIndex) {
                Object dataValue=variable.m_explicitDataValues.get(valueIndex);
                if (satisfiesNeighbors(variable,dataValue)) {
                    variable.m_dataValue=dataValue;
                    if (findAssignment(nodeIndex+1))
                        return true;
                }
                m_interruptFlag.checkInterrupt();
            }
            variable.m_dataValue=null;
            return false;
        }
    }
    protected boolean satisfiesNeighbors(DVariable variable,Object dataValue) {
        for (int neighborIndex=variable.m_unequalTo.size()-1;neighborIndex>=0;--neighborIndex) {
            Object neighborDataValue=variable.m_unequalTo.get(neighborIndex).m_dataValue;
            if (neighborDataValue!=null && neighborDataValue.equals(dataValue))
                return false;
        }
        return true;
    }
    protected void setClashFor(DVariable variable) {
        m_unionDependencySet.clearConstituents();
        loadAssertionDependencySets(variable);
        m_extensionManager.setClash(m_unionDependencySet);
    }
    protected void setClashFor(List<DVariable> variables) {
        m_unionDependencySet.clearConstituents();
        for (int nodeIndex=variables.size()-1;nodeIndex>=0;--nodeIndex) {
            DVariable variable=variables.get(nodeIndex);
            loadAssertionDependencySets(variable);
            for (int neighborIndex=variable.m_unequalToDirect.size()-1;neighborIndex>=0;--neighborIndex) {
                DVariable neighborVariable=variable.m_unequalToDirect.get(neighborIndex);
                DependencySet dependencySet=m_extensionManager.getAssertionDependencySet(Inequality.INSTANCE,variable.m_node,neighborVariable.m_node);
                m_unionDependencySet.addConstituent(dependencySet);
            }
        }
        m_extensionManager.setClash(m_unionDependencySet);
    }
    protected void loadAssertionDependencySets(DVariable variable) {
        Node node=variable.m_node;
        for (int index=variable.m_positiveDatatypeRestrictions.size()-1;index>=0;--index) {
            DataRange dataRange=variable.m_positiveDatatypeRestrictions.get(index);
            DependencySet dependencySet=m_extensionManager.getAssertionDependencySet(dataRange,node);
            m_unionDependencySet.addConstituent(dependencySet);
        }
        for (int index=variable.m_negativeDatatypeRestrictions.size()-1;index>=0;--index) {
            DataRange dataRange=(DataRange)variable.m_negativeDatatypeRestrictions.get(index).getNegation();
            DependencySet dependencySet=m_extensionManager.getAssertionDependencySet(dataRange,node);
            m_unionDependencySet.addConstituent(dependencySet);
        }
        for (int index=variable.m_positiveConstantEnumerations.size()-1;index>=0;--index) {
            DataRange dataRange=variable.m_positiveConstantEnumerations.get(index);
            DependencySet dependencySet=m_extensionManager.getAssertionDependencySet(dataRange,node);
            m_unionDependencySet.addConstituent(dependencySet);
        }
        for (int index=variable.m_negativeConstantEnumerations.size()-1;index>=0;--index) {
            DataRange dataRange=(DataRange)variable.m_negativeConstantEnumerations.get(index).getNegation();
            DependencySet dependencySet=m_extensionManager.getAssertionDependencySet(dataRange,node);
            m_unionDependencySet.addConstituent(dependencySet);
        }
    }

    public static class DConjunction implements Serializable {
        private static final long serialVersionUID = 3597740301361593691L;
        protected final List<DVariable> m_unusedVariables;
        protected final List<DVariable> m_usedVariables;
        protected final List<DVariable> m_activeVariables;
        protected DVariable[] m_buckets;
        protected int m_numberOfEntries;
        protected int m_resizeThreshold;

        public DConjunction() {
            m_unusedVariables=new ArrayList<DVariable>();
            m_usedVariables=new ArrayList<DVariable>();
            m_activeVariables=new ArrayList<DVariable>();
            m_buckets=new DVariable[16];
            m_resizeThreshold=(int)(m_buckets.length*0.75);
            m_numberOfEntries=0;
        }
        protected void clear() {
            for (int index=m_usedVariables.size()-1;index>=0;--index) {
                DVariable variable=m_usedVariables.get(index);
                variable.dispose();
                m_unusedVariables.add(variable);
            }
            m_usedVariables.clear();
            m_activeVariables.clear();
            Arrays.fill(m_buckets,null);
            m_numberOfEntries=0;
        }
        protected void clearActiveVariables() {
            for (int index=m_activeVariables.size()-1;index>=0;--index)
                m_activeVariables.get(index).clearEqualities();
            m_activeVariables.clear();
        }
        public List<DVariable> getActiveVariables() {
            return Collections.unmodifiableList(m_activeVariables);
        }
        public DVariable getVariableFor(Node node) {
            int index=getIndexFor(node.hashCode(),m_buckets.length);
            DVariable entry=m_buckets[index];
            while (entry!=null) {
                if (entry.m_node==node)
                    return entry;
                entry=entry.m_nextEntry;
            }
            return null;
        }
        protected DVariable getVariableForEx(Node node,boolean[] newVariableAdded) {
            int index=getIndexFor(node.hashCode(),m_buckets.length);
            DVariable entry=m_buckets[index];
            while (entry!=null) {
                if (entry.m_node==node) {
                    newVariableAdded[0]=false;
                    return entry;
                }
                entry=entry.m_nextEntry;
            }
            DVariable newVariable;
            if (m_unusedVariables.isEmpty())
                newVariable=new DVariable();
            else
                newVariable=m_unusedVariables.remove(m_unusedVariables.size()-1);
            newVariable.m_node=node;
            newVariable.m_nextEntry=m_buckets[index];
            m_buckets[index]=newVariable;
            m_numberOfEntries++;
            if (m_numberOfEntries>=m_resizeThreshold)
                resize(m_buckets.length*2);
            newVariableAdded[0]=true;
            m_usedVariables.add(newVariable);
            return newVariable;
        }
        protected void resize(int newCapacity) {
            DVariable[] newBuckets=new DVariable[newCapacity];
            for (int i=0;i<m_buckets.length;i++) {
                DVariable entry=m_buckets[i];
                while (entry!=null) {
                    DVariable nextEntry=entry.m_nextEntry;
                    int newIndex=getIndexFor(entry.m_node.hashCode(),newCapacity);
                    entry.m_nextEntry=newBuckets[newIndex];
                    newBuckets[newIndex]=entry;
                    entry=nextEntry;
                }
            }
            m_buckets=newBuckets;
            m_resizeThreshold=(int)(newCapacity*0.75);
        }
        protected void addInequality(DVariable node1,DVariable node2) {
            // Inequalities between nodes in the tableau are detected by the ExtensionManager.
            // Consequently, the DConjunction should not contain inequalities between DVariables.
            assert node1!=node2;
            if (!node1.m_unequalTo.contains(node2)) {
                node1.m_unequalTo.add(node2);
                node2.m_unequalTo.add(node1);
                node1.m_unequalToDirect.add(node2);
            }
        }
        public boolean isSymmetricClique() {
            // This method depends on the fact that there are no self-links.
            int numberOfVariables=m_activeVariables.size();
            if (numberOfVariables>0) {
                DVariable first=m_activeVariables.get(0);
                for (int variableIndex=numberOfVariables-1;variableIndex>=0;--variableIndex) {
                    DVariable variable=m_activeVariables.get(variableIndex);
                    if (variable.m_unequalTo.size()+1!=numberOfVariables || !first.hasSameRestrictions(variable))
                        return false;
                }
            }
            return true;
        }
        public String toString() {
            return toString(Prefixes.STANDARD_PREFIXES);
        }
        public String toString(Prefixes prefixes) {
            StringBuffer buffer=new StringBuffer();
            boolean first=true;
            for (int variableIndex=0;variableIndex<m_activeVariables.size();variableIndex++) {
                if (first)
                    first=false;
                else
                    buffer.append(" & ");
                DVariable variable=m_activeVariables.get(variableIndex);
                buffer.append(variable.toString(prefixes));
                buffer.append('(');
                buffer.append(variableIndex);
                buffer.append(')');
                for (int neighborIndex=0;neighborIndex<variable.m_unequalToDirect.size();neighborIndex++) {
                    buffer.append(" & ");
                    buffer.append(variableIndex);
                    buffer.append(" != ");
                    buffer.append(m_activeVariables.indexOf(variable.m_unequalToDirect.get(neighborIndex)));
                }
            }
            return buffer.toString();
        }
    }

    public static class DVariable implements Serializable {
        private static final long serialVersionUID = -2490195841140286089L;
        protected final List<ConstantEnumeration> m_positiveConstantEnumerations;
        protected final List<ConstantEnumeration> m_negativeConstantEnumerations;
        protected final List<DatatypeRestriction> m_positiveDatatypeRestrictions;
        protected final List<DatatypeRestriction> m_negativeDatatypeRestrictions;
        protected final List<DVariable> m_unequalTo;
        protected final List<DVariable> m_unequalToDirect;
        protected final List<Object> m_forbiddenDataValues;
        protected final List<Object> m_explicitDataValues;
        protected boolean m_hasExplicitDataValues;
        protected DatatypeRestriction m_mostSpecificRestriction;
        protected Node m_node;
        protected DVariable m_nextEntry;
        protected ValueSpaceSubset m_valueSpaceSubset;
        protected Object m_dataValue;

        protected DVariable() {
            m_positiveConstantEnumerations=new ArrayList<ConstantEnumeration>();
            m_negativeConstantEnumerations=new ArrayList<ConstantEnumeration>();
            m_positiveDatatypeRestrictions=new ArrayList<DatatypeRestriction>();
            m_negativeDatatypeRestrictions=new ArrayList<DatatypeRestriction>();
            m_unequalTo=new ArrayList<DVariable>();
            m_unequalToDirect=new ArrayList<DVariable>();
            m_forbiddenDataValues=new ArrayList<Object>();
            m_explicitDataValues=new ArrayList<Object>();
        }
        protected void dispose() {
            m_positiveConstantEnumerations.clear();
            m_negativeConstantEnumerations.clear();
            m_positiveDatatypeRestrictions.clear();
            m_negativeDatatypeRestrictions.clear();
            m_unequalTo.clear();
            m_unequalToDirect.clear();
            m_forbiddenDataValues.clear();
            m_explicitDataValues.clear();
            m_hasExplicitDataValues=false;
            m_mostSpecificRestriction=null;
            m_node=null;
            m_nextEntry=null;
            m_valueSpaceSubset=null;
            m_dataValue=null;
        }
        protected void clearEqualities() {
            m_unequalTo.clear();
            m_unequalToDirect.clear();
        }
        protected void addForbiddenDataValue(Object forbiddenDataValue) {
            if (!m_forbiddenDataValues.contains(forbiddenDataValue))
                m_forbiddenDataValues.add(forbiddenDataValue);
        }
        public boolean hasCardinalityAtLeast(int number) {
            if (m_hasExplicitDataValues)
                return m_explicitDataValues.size()>=number;
            else if (m_valueSpaceSubset!=null)
                return m_valueSpaceSubset.hasCardinalityAtLeast(number+m_forbiddenDataValues.size());
            else
                return true;
        }
        public Node getNode() {
            return m_node;
        }
        public List<ConstantEnumeration> getPositiveDataValueEnumerations() {
            return Collections.unmodifiableList(m_positiveConstantEnumerations);
        }
        public List<ConstantEnumeration> getNegativeDataValueEnumerations() {
            return Collections.unmodifiableList(m_negativeConstantEnumerations);
        }
        public List<DatatypeRestriction> getPositiveDatatypeRestrictions() {
            return Collections.unmodifiableList(m_positiveDatatypeRestrictions);
        }
        public List<DatatypeRestriction> getNegativeDatatypeRestrictions() {
            return Collections.unmodifiableList(m_negativeDatatypeRestrictions);
        }
        public List<DVariable> getUnequalToDirect() {
            return Collections.unmodifiableList(m_unequalToDirect);
        }
        public boolean hasSameRestrictions(DVariable that) {
            return this==that || (
                equals(m_positiveConstantEnumerations,that.m_positiveConstantEnumerations) &&
                equals(m_negativeConstantEnumerations,that.m_negativeConstantEnumerations) &&
                equals(m_positiveDatatypeRestrictions,that.m_positiveDatatypeRestrictions) &&
                equals(m_negativeDatatypeRestrictions,that.m_negativeDatatypeRestrictions)
            );
        }
        protected static <T> boolean equals(List<T> first,List<T> second) {
            if (first.size()!=second.size())
                return false;
            for (int index=first.size()-1;index>=0;--index) {
                T object=first.get(index);
                if (!second.contains(object))
                    return false;
            }
            return true;
        }
        public String toString() {
            return toString(Prefixes.STANDARD_PREFIXES);
        }
        public String toString(Prefixes prefixes) {
            StringBuffer buffer=new StringBuffer();
            boolean first=true;
            buffer.append('[');
            for (int index=0;index<m_positiveConstantEnumerations.size();index++) {
                if (first)
                    first=false;
                else
                    buffer.append(", ");
                buffer.append(m_positiveConstantEnumerations.get(index).toString(prefixes));
            }
            for (int index=0;index<m_negativeConstantEnumerations.size();index++) {
                if (first)
                    first=false;
                else
                    buffer.append(", ");
                buffer.append(m_negativeConstantEnumerations.get(index).getNegation().toString(prefixes));
            }
            for (int index=0;index<m_positiveDatatypeRestrictions.size();index++) {
                if (first)
                    first=false;
                else
                    buffer.append(", ");
                buffer.append(m_positiveDatatypeRestrictions.get(index).toString(prefixes));
            }
            for (int index=0;index<m_negativeDatatypeRestrictions.size();index++) {
                if (first)
                    first=false;
                else
                    buffer.append(", ");
                buffer.append(m_negativeDatatypeRestrictions.get(index).getNegation().toString(prefixes));
            }
            buffer.append(']');
            return buffer.toString();
        }
    }

    protected static int getIndexFor(int hashCode,int tableLength) {
        hashCode+=~(hashCode << 9);
        hashCode^=(hashCode >>> 14);
        hashCode+=(hashCode << 4);
        hashCode^=(hashCode >>> 10);
        return hashCode & (tableLength-1);
    }

    protected static class SmallestEnumerationFirst implements Comparator<DVariable>, Serializable {
        private static final long serialVersionUID = 8838838641444833249L;
        public static final Comparator<DVariable> INSTANCE=new SmallestEnumerationFirst();

        public int compare(DVariable o1,DVariable o2) {
            return o1.m_explicitDataValues.size()-o2.m_explicitDataValues.size();
        }

    }
}
TOP

Related Classes of org.semanticweb.HermiT.tableau.DatatypeManager$SmallestEnumerationFirst

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.