package uk.ac.manchester.cs.factplusplusad; import java.util.Iterator; import org.semanticweb.owlapi.model.HasOperands; import org.semanticweb.owlapi.model.OWLDataComplementOf; import org.semanticweb.owlapi.model.OWLDataHasValue; import org.semanticweb.owlapi.model.OWLDataIntersectionOf; import org.semanticweb.owlapi.model.OWLDataOneOf; import org.semanticweb.owlapi.model.OWLDataUnionOf; import org.semanticweb.owlapi.model.OWLDatatype; import org.semanticweb.owlapi.model.OWLDatatypeRestriction; import org.semanticweb.owlapi.model.OWLEntity; import org.semanticweb.owlapi.model.OWLLiteral; import org.semanticweb.owlapi.model.OWLObject; import org.semanticweb.owlapi.model.OWLObjectComplementOf; import org.semanticweb.owlapi.model.OWLObjectHasSelf; import org.semanticweb.owlapi.model.OWLObjectHasValue; import org.semanticweb.owlapi.model.OWLObjectIntersectionOf; import org.semanticweb.owlapi.model.OWLObjectInverseOf; import org.semanticweb.owlapi.model.OWLObjectOneOf; import org.semanticweb.owlapi.model.OWLObjectPropertyExpression; import org.semanticweb.owlapi.model.OWLObjectUnionOf; import org.semanticweb.owlapi.model.OWLPropertyExpression; import org.semanticweb.owlapi.model.OWLPropertyRange; import org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom; import org.semanticweb.owlapi.vocab.OWLRDFVocabulary; /** * Determine how many instances can an expression have. All methods return maximal n such that * expr\in C^{>= n}, n >= 1 */ class LowerBoundDirectEvaluator extends CardinalityEvaluatorBase { LowerBoundDirectEvaluator(Signature s) { super(s); } @Override int getNoneValue() { return 0; } @Override int getAllValue() { return -1; } @Override int getOneNoneLower(boolean v) { return v ? 1 : getNoneValue(); } // TODO: checks only C top-locality, not R @Override int getEntityValue(OWLEntity entity) { if (entity.isTopEntity()) { if (OWLRDFVocabulary.OWL_THING.getIRI().equals(entity.getIRI())) { return 1; } return anyLowerValue(); } if (entity.isBottomEntity()) { return noLowerValue(); } return getOneNoneLower(topCLocal() && nc(entity)); } /** * helper for All */ @Override int getForallValue(OWLPropertyExpression r, OWLPropertyRange c) { return getOneNoneLower(isBotEquivalent(r) || isUpperLE(getUpperBoundComplement(c), 0)); } @Override int getMinValue(int m, OWLPropertyExpression r, OWLPropertyRange c) { // m == 0 or... if (m == 0) { return anyLowerValue(); } // R = \top and... if (!isTopEquivalent(r)) { return noLowerValue(); } // C \in C^{>= m} return isLowerGE(getLowerBoundDirect(c), m) ? m : noLowerValue(); } @Override int getMaxValue(int m, OWLPropertyExpression r, OWLPropertyRange c) { // R = \bot or... if (isBotEquivalent(r)) { return 1; } // C\in C^{<= m} return getOneNoneLower(isUpperLE(getUpperBoundDirect(c), m)); } @Override int getExactValue(int m, OWLPropertyExpression r, OWLPropertyRange c) { int min = getMinValue(m, r, c), max = getMaxValue(m, r, c); // we need to take the lowest value if (min == noLowerValue() || max == noLowerValue()) { return noLowerValue(); } if (min == anyLowerValue()) { return max; } if (max == anyLowerValue()) { return min; } return Math.min(min, max); } // FIXME!! not done yet <C extends OWLObject> int getAndValue(HasOperands<C> expr) { // return m - sumK, where // true if found a conjunct that is in C^{>=} boolean foundC = false; int foundM = 0; // the m- and k- values for the C_j with max m+k int mMax = 0, kMax = 0; // sum of all known k int sumK = 0; // 1st pass: check for none-case, deals with deterministic cases Iterator<C> it = expr.operands().iterator(); while (it.hasNext()) { C p = it.next(); // C_j \in C^{>= m} int m = getLowerBoundDirect(p); // C_j \in CC^{<= k} int k = getUpperBoundComplement(p); // note bound flip for K // case 0: if both aren't known then we don't know if (m == noLowerValue() && k == noUpperValue()) { return noLowerValue(); } // if only k exists then add it to k if (m == noLowerValue()) { sumK += k; continue; } // if only m exists then set it to m if (k == noUpperValue()) { if (foundC) { return noLowerValue(); } foundC = true; foundM = m; continue; } // here both k and m are values // count k for the sumK += k; if (k + m > kMax + mMax) { kMax = k; mMax = m; } } // here we know the best candidate for M, and only need to set it up if (foundC) { // found during the deterministic case foundM -= sumK; return foundM > 0 ? foundM : noLowerValue(); } else { // no deterministic option; choose the best one sumK -= kMax; mMax -= sumK; return mMax > 0 ? mMax : noLowerValue(); } } <C extends OWLObject> int getOrValue(HasOperands<C> expr) { int max = noLowerValue(); // we are looking for the maximal value here; ANY need to be // special-cased Iterator<C> it = expr.operands().iterator(); while (it.hasNext()) { C p = it.next(); int n = getLowerBoundDirect(p); if (n == anyLowerValue()) { return anyLowerValue(); } max = Math.max(max, n); } return max; } // concept expressions @Override public void visit(OWLObjectComplementOf expr) { value = getLowerBoundComplement(expr.getOperand()); } @Override public void visit(OWLObjectIntersectionOf expr) { value = getAndValue(expr); } @Override public void visit(OWLObjectUnionOf expr) { value = getOrValue(expr); } @Override public void visit(OWLObjectOneOf expr) { value = getOneNoneLower(expr.individuals().count() > 0); } @Override public void visit(OWLObjectHasSelf expr) { value = getOneNoneLower(isTopEquivalent(expr.getProperty())); } // FIXME!! differ from the paper @Override public void visit(OWLObjectHasValue expr) { value = getOneNoneLower(isTopEquivalent(expr.getProperty())); } @Override public void visit(OWLDataHasValue expr) { value = getOneNoneLower(isTopEquivalent(expr.getProperty())); } // object role expressions @Override public void visit(OWLObjectInverseOf expr) { value = getLowerBoundDirect(expr.getInverseProperty()); } @Override public void visit(OWLSubPropertyChainOfAxiom expr) { for (OWLObjectPropertyExpression p : expr.getPropertyChain()) { if (!isTopEquivalent(p)) { value = noLowerValue(); return; } } value = anyLowerValue(); } // negated datatype is a union of all other DTs that are infinite @Override public void visit(OWLDatatype o) { value = noLowerValue(); } // negated restriction include negated DT @Override public void visit(OWLDatatypeRestriction o) { value = noLowerValue(); } @Override public void visit(OWLLiteral o) { value = noLowerValue(); } @Override public void visit(OWLDataComplementOf expr) { value = getLowerBoundComplement(expr.getDataRange()); } @Override public void visit(OWLDataIntersectionOf expr) { value = getAndValue(expr); } @Override public void visit(OWLDataUnionOf expr) { value = getOrValue(expr); } @Override public void visit(OWLDataOneOf expr) { value = getOneNoneLower(expr.values().count() > 0); } }