All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.semanticweb.elk.reasoner.saturation.properties.ObjectPropertyTaxonomyComputationFactory Maven / Gradle / Ivy

There is a newer version: 0.29.0
Show newest version
/*
 * #%L
 * ELK Reasoner
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2016 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.saturation.properties;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.semanticweb.elk.owl.interfaces.ElkEntity;
import org.semanticweb.elk.owl.interfaces.ElkObjectProperty;
import org.semanticweb.elk.owl.predefined.PredefinedElkObjectPropertyFactory;
import org.semanticweb.elk.reasoner.indexing.model.IndexedObjectProperty;
import org.semanticweb.elk.reasoner.indexing.model.OntologyIndex;
import org.semanticweb.elk.util.collections.ArrayHashMap;
import org.semanticweb.elk.util.collections.ArrayHashSet;
import org.semanticweb.elk.util.collections.Operations;
import org.semanticweb.elk.util.concurrent.computation.InputProcessor;
import org.semanticweb.elk.util.concurrent.computation.InputProcessorFactory;
import org.semanticweb.elk.util.concurrent.computation.InterruptMonitor;
import org.semanticweb.elk.util.concurrent.computation.DelegateInterruptMonitor;

/**
 * Computes object property taxonomy.
 * 
 * @author Peter Skocovsky
 */
public class ObjectPropertyTaxonomyComputationFactory
		extends DelegateInterruptMonitor implements
		InputProcessorFactory {

	/**
	 * Visitor accepting results of the transitive reduction.
	 */
	private final TransitiveReductionOutputVisitor outputProcessor_;

	private final IndexedObjectProperty indexedTopProperty_;

	private final IndexedObjectProperty indexedBottomProperty_;

	private final Collection> defaultDirectSubproperties_;

	public ObjectPropertyTaxonomyComputationFactory(
			final InterruptMonitor interrupter,
			final TransitiveReductionOutputVisitor outputProcessor,
			final OntologyIndex index,
			final PredefinedElkObjectPropertyFactory predefinedFactory) {
		super(interrupter);
		this.outputProcessor_ = outputProcessor;
		this.indexedTopProperty_ = index.getOwlTopObjectProperty();
		this.indexedBottomProperty_ = index.getOwlBottomObjectProperty();
		this.defaultDirectSubproperties_ = Collections.singleton(Collections
				.singleton(predefinedFactory.getOwlBottomObjectProperty()));
	}

	@Override
	public Engine getEngine() {
		return new Engine();
	}

	@Override
	public void finish() {
		// Empty.
	}

	class Engine implements InputProcessor {

		@Override
		public void submit(final IndexedObjectProperty property) {
			instertIntoTaxonomy(property);
		}

		@Override
		public void process() throws InterruptedException {
			// Everything is done in submit().
		}

		@Override
		public void finish() {
			// Empty.
		}

	}

	/**
	 * Adds the specified object property into the taxonomy if it is not in it
	 * yet and sets its direct sub-properties if not set yet.
	 * 
	 * @param property
	 *            The property that should be inserted into taxonomy.
	 */
	private void instertIntoTaxonomy(final IndexedObjectProperty property) {

		/* 
		 * @formatter:off
		 * 
		 * Transitive reduction and taxonomy computation
		 * 	if sub-properties of a sub-property contain this property,
		 * 		they are equivalent
		 * 	if a property is a strict sub-property of another strict sub-property,
		 * 		it is not direct
		 * 
		 * @formatter:on
		 */

		final Map equivalent = collectEquivalent(
				property);
		if (equivalent == null) {
			// Equivalent to top.
			return;
		}
		final Map> subEquivalent = new ArrayHashMap>();
		final Set indirect = new ArrayHashSet();
		for (final IndexedObjectProperty subProperty : property.getSaturated()
				.getSubProperties()) {

			if (equivalent.containsKey(subProperty)) {
				// subProperty is not strict
				continue;
			}
			// subProperty is strict

			final Map subEq = collectEquivalent(
					subProperty);
			// should not be null, because top cannot be a strict sub-property
			subEquivalent.put(subProperty, subEq.values());
			for (final IndexedObjectProperty subSubProperty : subProperty
					.getSaturated().getSubProperties()) {
				if (!subEq.containsKey(subSubProperty)) {
					// strict
					indirect.add(subSubProperty);
				}
			}

		}

		/*
		 * If property is not equivalent to bottom and there are no strict sub
		 * properties, add the bottom as a default sub property.
		 */
		if (subEquivalent.isEmpty() && (indexedBottomProperty_ == null
				|| !equivalent.containsKey(indexedBottomProperty_))) {
			outputProcessor_
					.visit(new TransitiveReductionOutputEquivalentDirectImpl(
							equivalent.values(), defaultDirectSubproperties_));
			return;
		}
		// else

		final Collection> direct = Operations
				.map(subEquivalent.entrySet(),
						new Operations.Transformation>, Collection>() {

							@Override
							public Collection transform(
									final Entry> element) {
								if (indirect.contains(element.getKey())) {
									return null;
								}
								// else
								return element.getValue();
							}

						});

		outputProcessor_
				.visit(new TransitiveReductionOutputEquivalentDirectImpl(
						equivalent.values(), direct));

	}

	/**
	 * Collects sub-properties of property that are equivalent to
	 * it. Returns null if property is equivalent to
	 * the top property.
	 * 
	 * @param property
	 * @return null if the specified property is equivalent to the
	 *         top property, otherwise mapping from equivalent indexed
	 *         properties to their elk entities.
	 */
	private Map collectEquivalent(
			final IndexedObjectProperty property) {

		final Set subProperties = property.getSaturated()
				.getSubProperties();
		final Map equivalent = new ArrayHashMap();
		for (final IndexedObjectProperty subProperty : subProperties) {
			if (subProperty.equals(indexedTopProperty_)) {
				outputProcessor_
						.visit(new TransitiveReductionOutputExtremeImpl(
								property.getElkEntity()));
				return null;
			}
			if (subProperty.getSaturated().getSubProperties().contains(property)
					|| property.equals(indexedBottomProperty_)) {
				equivalent.put(subProperty, subProperty.getElkEntity());
			}
		}
		if (indexedBottomProperty_.getSaturated().getSubProperties()
				.contains(property)) {
			equivalent.put(indexedBottomProperty_,
					indexedBottomProperty_.getElkEntity());
		}

		return equivalent;
	}

	private static class TransitiveReductionOutputEquivalentDirectImpl
			implements TransitiveReductionOutputEquivalentDirect {

		final Collection equivalent_;
		final Collection> direct_;

		public TransitiveReductionOutputEquivalentDirectImpl(
				final Collection equivalent,
				final Collection> direct) {
			this.equivalent_ = equivalent;
			this.direct_ = direct;
		}

		@Override
		public Collection getEquivalent() {
			return equivalent_;
		}

		@Override
		public Iterable> getDirectlyRelated() {
			return Collections.unmodifiableCollection(direct_);
		}

		@Override
		public void accept(final TransitiveReductionOutputVisitor visitor) {
			visitor.visit(this);
		}

	}

	private static class TransitiveReductionOutputExtremeImpl
			implements TransitiveReductionOutputExtreme {

		final E extremeMember_;

		public TransitiveReductionOutputExtremeImpl(final E extremeMember) {
			this.extremeMember_ = extremeMember;
		}

		@Override
		public E getExtremeMember() {
			return extremeMember_;
		}

		@Override
		public void accept(final TransitiveReductionOutputVisitor visitor) {
			visitor.visit(this);
		}

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy