org.semanticweb.elk.reasoner.indexing.hierarchy.IndexedObjectSomeValuesFrom Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elk-reasoner Show documentation
Show all versions of elk-reasoner Show documentation
ELK consequence-based reasoning engine
/*
* #%L
* elk-reasoner
*
* $Id$
* $HeadURL$
* %%
* Copyright (C) 2011 Department of Computer Science, University of Oxford
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package org.semanticweb.elk.reasoner.indexing.hierarchy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import org.apache.log4j.Logger;
import org.semanticweb.elk.owl.interfaces.ElkObjectSomeValuesFrom;
import org.semanticweb.elk.reasoner.indexing.visitors.IndexedClassExpressionVisitor;
import org.semanticweb.elk.reasoner.indexing.visitors.IndexedObjectSomeValuesFromVisitor;
import org.semanticweb.elk.reasoner.saturation.BasicSaturationStateWriter;
import org.semanticweb.elk.reasoner.saturation.conclusions.NegativeSubsumer;
import org.semanticweb.elk.reasoner.saturation.conclusions.Propagation;
import org.semanticweb.elk.reasoner.saturation.context.Context;
import org.semanticweb.elk.reasoner.saturation.rules.ChainableRule;
import org.semanticweb.elk.reasoner.saturation.rules.DecompositionRuleApplicationVisitor;
import org.semanticweb.elk.reasoner.saturation.rules.RuleApplicationVisitor;
import org.semanticweb.elk.util.collections.LazySetIntersection;
import org.semanticweb.elk.util.collections.chains.Chain;
import org.semanticweb.elk.util.collections.chains.Matcher;
import org.semanticweb.elk.util.collections.chains.ModifiableLinkImpl;
import org.semanticweb.elk.util.collections.chains.ReferenceFactory;
import org.semanticweb.elk.util.collections.chains.SimpleTypeBasedMatcher;
/**
* Represents all occurrences of an {@link ElkObjectSomeValuesFrom} in an
* ontology.
*
* @author Frantisek Simancik
* @author "Yevgeny Kazakov"
*
*/
public class IndexedObjectSomeValuesFrom extends IndexedClassExpression {
protected static final Logger LOGGER_ = Logger
.getLogger(IndexedObjectSomeValuesFrom.class);
protected final IndexedObjectProperty property;
protected final IndexedClassExpression filler;
IndexedObjectSomeValuesFrom(IndexedObjectProperty indexedObjectProperty,
IndexedClassExpression filler) {
this.property = indexedObjectProperty;
this.filler = filler;
}
/**
* @return The indexed object property comprising this ObjectSomeValuesFrom.
*/
public IndexedObjectProperty getRelation() {
return property;
}
/**
* @return The indexed class expression comprising this
* ObjectSomeValuesFrom.
*/
public IndexedClassExpression getFiller() {
return filler;
}
public O accept(IndexedObjectSomeValuesFromVisitor visitor) {
return visitor.visit(this);
}
@Override
public O accept(IndexedClassExpressionVisitor visitor) {
return accept((IndexedObjectSomeValuesFromVisitor) visitor);
}
@Override
protected void updateOccurrenceNumbers(final ModifiableOntologyIndex index,
final int increment, final int positiveIncrement,
final int negativeIncrement) {
if (negativeOccurrenceNo == 0 && negativeIncrement > 0) {
// first negative occurrence of this expression
// register the composition rule for the filler
index.add(filler, new ThisCompositionRule(this));
}
positiveOccurrenceNo += positiveIncrement;
negativeOccurrenceNo += negativeIncrement;
if (negativeOccurrenceNo == 0 && negativeIncrement < 0) {
// no negative occurrences of this expression left
index.remove(filler, new ThisCompositionRule(this));
}
}
@Override
public String toStringStructural() {
return "ObjectSomeValuesFrom(" + this.property + ' ' + this.filler
+ ')';
}
@Override
public void accept(DecompositionRuleApplicationVisitor visitor,
Context context) {
visitor.visit(this, context);
}
public static void generatePropagations(BasicSaturationStateWriter writer,
IndexedPropertyChain property, Context context) {
for (IndexedClassExpression ice : context.getSubsumers()) {
ThisCompositionRule rule = ice.getCompositionRuleChain().find(
ThisCompositionRule.MATCHER_);
if (rule == null)
continue;
rule.apply(writer, property, context);
}
}
/**
*
*/
public static class ThisCompositionRule extends
ModifiableLinkImpl> implements
ChainableRule {
private static final String NAME = "ObjectSomeValuesFrom Introduction";
private final Collection negExistentials_;
private ThisCompositionRule(ChainableRule next) {
super(next);
this.negExistentials_ = new ArrayList(
1);
}
ThisCompositionRule(IndexedObjectSomeValuesFrom negExistential) {
super(null);
this.negExistentials_ = new ArrayList(
1);
this.negExistentials_.add(negExistential);
}
// TODO: hide this method
public Collection getNegativeExistentials() {
return negExistentials_;
}
@Override
public String getName() {
return NAME;
}
@Override
public void apply(BasicSaturationStateWriter writer, Context context) {
if (LOGGER_.isTraceEnabled()) {
LOGGER_.trace("Applying " + NAME + " to " + context);
}
final Set candidatePropagationProperties = context
.getBackwardLinksByObjectProperty().keySet();
// TODO: deal with reflexive roles using another composition
// rule and uncomment this
// if (candidatePropagationProperties.isEmpty()) {
// return;
// }
for (IndexedObjectSomeValuesFrom e : negExistentials_) {
IndexedPropertyChain relation = e.getRelation();
/*
* creating propagations for relevant sub-properties of the
* relation
*/
for (IndexedPropertyChain property : new LazySetIntersection(
candidatePropagationProperties, relation.getSaturated()
.getSubProperties())) {
writer.produce(context, new Propagation(property, e));
}
// TODO: create a composition rule to deal with reflexivity
// propagating to the this context if relation is reflexive
if (relation.getSaturated().isDerivedReflexive())
writer.produce(context, new NegativeSubsumer(e));
}
}
@Override
public boolean addTo(Chain> ruleChain) {
ThisCompositionRule rule = ruleChain.getCreate(MATCHER_, FACTORY_);
boolean changed = false;
for (IndexedObjectSomeValuesFrom negExistential : negExistentials_) {
changed |= rule.addNegExistential(negExistential);
}
return changed;
}
@Override
public boolean removeFrom(Chain> ruleChain) {
boolean changed = false;
ThisCompositionRule rule = ruleChain.find(MATCHER_);
if (rule != null) {
for (IndexedObjectSomeValuesFrom negExistential : negExistentials_) {
changed |= rule.removeNegExistential(negExistential);
}
if (rule.isEmpty()) {
ruleChain.remove(MATCHER_);
changed = true;
}
}
return changed;
}
@Override
public void accept(RuleApplicationVisitor visitor,
BasicSaturationStateWriter writer, Context context) {
visitor.visit(this, writer, context);
}
private boolean addNegExistential(
IndexedObjectSomeValuesFrom existential) {
return negExistentials_.add(existential);
}
private boolean removeNegExistential(
IndexedObjectSomeValuesFrom existential) {
return negExistentials_.remove(existential);
}
/**
* @return {@code true} if this rule never does anything
*/
private boolean isEmpty() {
return negExistentials_.isEmpty();
}
private void apply(BasicSaturationStateWriter writer,
IndexedPropertyChain property, Context context) {
for (IndexedObjectSomeValuesFrom e : negExistentials_) {
if (e.getRelation().getSaturated().getSubProperties()
.contains(property)) {
writer.produce(context, new Propagation(property, e));
}
}
}
private static final Matcher, ThisCompositionRule> MATCHER_ = new SimpleTypeBasedMatcher, ThisCompositionRule>(
ThisCompositionRule.class);
private static final ReferenceFactory, ThisCompositionRule> FACTORY_ = new ReferenceFactory, ThisCompositionRule>() {
@Override
public ThisCompositionRule create(ChainableRule next) {
return new ThisCompositionRule(next);
}
};
}
}