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

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

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

import org.semanticweb.elk.reasoner.indexing.model.IndexedComplexPropertyChain;
import org.semanticweb.elk.reasoner.indexing.model.IndexedObjectProperty;
import org.semanticweb.elk.reasoner.indexing.model.IndexedPropertyChain;
import org.semanticweb.elk.reasoner.proof.ReasonerProducer;
import org.semanticweb.elk.reasoner.saturation.properties.inferences.ObjectPropertyInference;
import org.semanticweb.elk.reasoner.stages.PropertyHierarchyCompositionState;
import org.semanticweb.elk.util.collections.AbstractHashMultimap;
import org.semanticweb.elk.util.collections.ArrayHashSet;
import org.semanticweb.elk.util.concurrent.computation.DelegateInterruptMonitor;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A factory of engines for computing sub-properties and compositions induced by
 * property inclusions, property chains, and reflexive properties
 * 
 * @author "Yevgeny Kazakov"
 * 
 */
public class PropertyHierarchyCompositionComputationFactory extends
		DelegateInterruptMonitor
		implements
		InputProcessorFactory {

	// logger for this class
	private static final Logger LOGGER_ = LoggerFactory
			.getLogger(PropertyHierarchyCompositionComputationFactory.class);

	/**
	 * used to record sub-property inferences
	 */
	private final ReasonerProducer inferenceProducer_;

	/**
	 * The dispatcher of events over derived property hierarchy and
	 * compositions.
	 */
	private final PropertyHierarchyCompositionState.Dispatcher dispatcher_;
	
	public PropertyHierarchyCompositionComputationFactory(
			final InterruptMonitor interrupter,
			ReasonerProducer inferenceProducer,
			final PropertyHierarchyCompositionState.Dispatcher dispatcher) {
		super(interrupter);
		this.inferenceProducer_ = inferenceProducer;
		this.dispatcher_ = dispatcher;
	}

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

	@Override
	public void finish() {
		// nothing to do
	}

	class Engine implements InputProcessor {

		@Override
		public void submit(IndexedPropertyChain job) {
			job.accept(PROCESSOR_);
		}

		@Override
		public void process() throws InterruptedException {
			// everything should be process during submission
		}

		@Override
		public void finish() {
			// nothing to do
		}

	}

	private final IndexedPropertyChain.Visitor PROCESSOR_ = new IndexedPropertyChain.Visitor() {

		@Override
		public Void visit(IndexedObjectProperty element) {
			LOGGER_.trace("{}: computing sub-property chains and ranges",
					element);
			// ensure that sub-properties are computed
			SubPropertyExplorer.getSubPropertyChains(element,
					inferenceProducer_, dispatcher_);
			// ensure that property ranges are computed
			RangeExplorer.getRanges(element, inferenceProducer_);
			// TODO: verify that global restrictions on range axioms are
			// satisfied:
			// http://www.w3.org/TR/owl2-profiles/#Global_Restrictions
			return null;
		}

		@Override
		public Void visit(IndexedComplexPropertyChain element) {
			LOGGER_.trace("{}: computing compositions", element);

			IndexedObjectProperty left = element.getFirstProperty();
			IndexedPropertyChain right = element.getSuffixChain();
			Set leftSubProperties = SubPropertyExplorer
					.getSubProperties(left, inferenceProducer_,
							dispatcher_);
			if (leftSubProperties.isEmpty())
				return null;
			Set rightSubProperties = SubPropertyExplorer
					.getSubPropertyChains(right, inferenceProducer_,
							dispatcher_);

			for (IndexedPropertyChain rightSubPropertyChain : rightSubProperties) {

				if (left == right && rightSubPropertyChain == element) {
					// a special but very common case with transitivity axiom when
					// all compositions are redundant and not needed for tracing
					LOGGER_.trace(
							"{} o {} => {}: transitivity composition [ignored]",
							left, rightSubPropertyChain, element);
					continue;
				}				
				
				// computing left properties for which composition with the
				// current right sub-property chain is redundant
				Collection redundantLeftProperties = Collections
						.emptySet();

				if (rightSubPropertyChain instanceof IndexedComplexPropertyChain) {
					IndexedComplexPropertyChain composition = (IndexedComplexPropertyChain) rightSubPropertyChain;
					IndexedPropertyChain rightRightSubProperty = composition
							.getSuffixChain();
					if (rightSubProperties.contains(rightRightSubProperty)) {
						IndexedObjectProperty rightLeftSubProperty = composition
								.getFirstProperty();
						redundantLeftProperties = SubPropertyExplorer
								.getLeftSubComposableSubPropertiesByRightProperties(
										left, inferenceProducer_,
										dispatcher_).get(
										rightLeftSubProperty);
					}
				}

				SaturatedPropertyChain rightSaturation = rightSubPropertyChain
						.getSaturated();
				synchronized (rightSaturation) {
					if (rightSaturation.nonRedundantCompositionsByLeftSubProperty == null) {
						rightSaturation.nonRedundantCompositionsByLeftSubProperty = new CompositionMultimap();
					}
				}
				
				if (!redundantLeftProperties.isEmpty()) {
					synchronized (rightSaturation) {
						if (rightSaturation.redundantCompositionsByLeftSubProperty == null) {
							rightSaturation.redundantCompositionsByLeftSubProperty = new CompositionMultimap();
						}
					}
				}
				
				for (IndexedObjectProperty leftSubProperty : leftSubProperties) {
					boolean newRecord = false;

					boolean redundant = redundantLeftProperties.contains(leftSubProperty);

					if (LOGGER_.isTraceEnabled()) {
						LOGGER_.trace("{} o {} => {}: new composition [redundant: {}]",
								leftSubProperty, rightSubPropertyChain, element, redundant);
					}

					AbstractHashMultimap compositionsByLeft = redundant
							? rightSaturation.redundantCompositionsByLeftSubProperty
							: rightSaturation.nonRedundantCompositionsByLeftSubProperty;
					
					Collection compositionsSoFar;
					
					synchronized (compositionsByLeft) {
						compositionsSoFar = compositionsByLeft
								.getValues(leftSubProperty);
						if (compositionsSoFar == null) {
							compositionsSoFar = new ArrayHashSet(
									2);
							compositionsByLeft.put(leftSubProperty,
									compositionsSoFar);
							newRecord = true;
						}
					}

					if (newRecord) {
						SaturatedPropertyChain leftSaturation = leftSubProperty
								.getSaturated();
						Map> compositionsByRight;
						if (redundant) {
							synchronized (leftSaturation) {
								if (leftSaturation.redundantCompositionsByRightSubProperty == null)
									leftSaturation.redundantCompositionsByRightSubProperty = new CompositionMultimap();
							}
							compositionsByRight = leftSaturation.redundantCompositionsByRightSubProperty;
						} else {
							synchronized (leftSaturation) {
								if (leftSaturation.nonRedundantCompositionsByRightSubProperty == null)
									leftSaturation.nonRedundantCompositionsByRightSubProperty = new CompositionMultimap();
							}
							compositionsByRight = leftSaturation.nonRedundantCompositionsByRightSubProperty;
						}
						
						synchronized (compositionsByRight) {
							compositionsByRight.put(rightSubPropertyChain,
									compositionsSoFar);
						}
					}

					synchronized (compositionsSoFar) {
						compositionsSoFar.add(element);
					}
				}
			}
			return null;
		}

	};

	private static class CompositionMultimap

extends AbstractHashMultimap { @Override protected Collection newRecord() { return new ArrayHashSet(2); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy