elk-reasoner/src/main/java/org/semanticweb/elk/reasoner/saturation/properties/SubPropertyExplorer.java
static Multimap<IndexedObjectProperty, IndexedObjectProperty> getLeftSubComposableSubPropertiesByRightProperties(
			IndexedObjectProperty input,
			Producer<? super SubPropertyChainInference> inferenceProducer,
			final PropertyHierarchyCompositionState.Dispatcher dispatcher) {
		SaturatedPropertyChain saturation = input.getSaturated();
		if (saturation.leftSubComposableSubPropertiesByRightPropertiesComputed)
			return saturation.leftSubComposableSubPropertiesByRightProperties;
		// else
		synchronized (saturation) {
			if (saturation.leftSubComposableSubPropertiesByRightProperties == null)
				saturation.leftSubComposableSubPropertiesByRightProperties = new HashSetMultimap<IndexedObjectProperty, IndexedObjectProperty>();
		}
		synchronized (saturation.leftSubComposableSubPropertiesByRightProperties) {
			if (saturation.leftSubComposableSubPropertiesByRightPropertiesComputed)
				return saturation.leftSubComposableSubPropertiesByRightProperties;
			// else compute it
			Set<IndexedObjectProperty> subProperties = getSubProperties(input,
					inferenceProducer, dispatcher);
			for (IndexedPropertyChain subPropertyChain : getSubPropertyChains(
					input, inferenceProducer, dispatcher)) {
				if (subPropertyChain instanceof IndexedComplexPropertyChain) {
					IndexedComplexPropertyChain composition = (IndexedComplexPropertyChain) subPropertyChain;
					Set<IndexedObjectProperty> leftSubProperties = getSubProperties(
							composition.getFirstProperty(), inferenceProducer,
							dispatcher);
					Set<IndexedObjectProperty> commonSubProperties = new LazySetIntersection<IndexedObjectProperty>(
							subProperties, leftSubProperties);
					if (commonSubProperties.isEmpty())
						continue;
					// else
					for (IndexedObjectProperty rightSubProperty : getSubProperties(
							composition.getSuffixChain(), inferenceProducer,
							dispatcher))
						for (IndexedObjectProperty commonLeft : commonSubProperties)
							saturation.leftSubComposableSubPropertiesByRightProperties
									.add(rightSubProperty, commonLeft);
				}
			}
			saturation.leftSubComposableSubPropertiesByRightPropertiesComputed = true;
		}
		return saturation.leftSubComposableSubPropertiesByRightProperties;
	}
static Multimap<IndexedObjectProperty, IndexedObjectProperty> getLeftSubComposableSubPropertiesByRightProperties(
			IndexedObjectProperty input,
			Producer<? super SubPropertyChainInference> inferenceProducer,
			final PropertyHierarchyCompositionState.Dispatcher dispatcher) {
		SaturatedPropertyChain saturation = input.getSaturated();
		if (saturation.leftSubComposableSubPropertiesByRightPropertiesComputed)
			return saturation.leftSubComposableSubPropertiesByRightProperties;
		// else
		synchronized (saturation) {
			if (saturation.leftSubComposableSubPropertiesByRightProperties == null)
				saturation.leftSubComposableSubPropertiesByRightProperties = new HashSetMultimap<IndexedObjectProperty, IndexedObjectProperty>();
		}
		synchronized (saturation.leftSubComposableSubPropertiesByRightProperties) {
			if (saturation.leftSubComposableSubPropertiesByRightPropertiesComputed)
				return saturation.leftSubComposableSubPropertiesByRightProperties;
			// else compute it
			Set<IndexedObjectProperty> subProperties = getSubProperties(input,
					inferenceProducer, dispatcher);
			for (IndexedPropertyChain subPropertyChain : getSubPropertyChains(
					input, inferenceProducer, dispatcher)) {
				if (subPropertyChain instanceof IndexedComplexPropertyChain) {
					IndexedComplexPropertyChain composition = (IndexedComplexPropertyChain) subPropertyChain;
					Set<IndexedObjectProperty> leftSubProperties = getSubProperties(
							composition.getFirstProperty(), inferenceProducer,
							dispatcher);
					Set<IndexedObjectProperty> commonSubProperties = new LazySetIntersection<IndexedObjectProperty>(
							subProperties, leftSubProperties);
					if (commonSubProperties.isEmpty())
						continue;
					// else
					for (IndexedObjectProperty rightSubProperty : getSubProperties(
							composition.getSuffixChain(), inferenceProducer,
							dispatcher))
						for (IndexedObjectProperty commonLeft : commonSubProperties)
							saturation.leftSubComposableSubPropertiesByRightProperties
									.add(rightSubProperty, commonLeft);
				}
			}
			saturation.leftSubComposableSubPropertiesByRightPropertiesComputed = true;
		}
		return saturation.leftSubComposableSubPropertiesByRightProperties;
	}
static Multimap < IndexedObjectProperty , IndexedObjectProperty > getLeftSubComposableSubPropertiesByRightProperties ( IndexedObjectProperty input , Producer < ? super SubPropertyChainInference > inferenceProducer , final PropertyHierarchyCompositionState . Dispatcher dispatcher ) { SaturatedPropertyChain saturation = input . getSaturated ( ) ; if ( saturation . leftSubComposableSubPropertiesByRightPropertiesComputed ) return saturation . leftSubComposableSubPropertiesByRightProperties ; // else synchronized ( saturation ) { if ( saturation . leftSubComposableSubPropertiesByRightProperties == null ) saturation . leftSubComposableSubPropertiesByRightProperties = new HashSetMultimap < IndexedObjectProperty , IndexedObjectProperty > ( ) ; } synchronized ( saturation . leftSubComposableSubPropertiesByRightProperties ) { if ( saturation . leftSubComposableSubPropertiesByRightPropertiesComputed ) return saturation . leftSubComposableSubPropertiesByRightProperties ; // else compute it Set < IndexedObjectProperty > subProperties = getSubProperties ( input , inferenceProducer , dispatcher ) ; for ( IndexedPropertyChain subPropertyChain : getSubPropertyChains ( input , inferenceProducer , dispatcher ) ) { if ( subPropertyChain instanceof IndexedComplexPropertyChain ) { IndexedComplexPropertyChain composition = ( IndexedComplexPropertyChain ) subPropertyChain ; Set < IndexedObjectProperty > leftSubProperties = getSubProperties ( composition . getFirstProperty ( ) , inferenceProducer , dispatcher ) ; Set < IndexedObjectProperty > commonSubProperties = new LazySetIntersection < IndexedObjectProperty > ( subProperties , leftSubProperties ) ; if ( commonSubProperties . isEmpty ( ) ) continue ; // else for ( IndexedObjectProperty rightSubProperty : getSubProperties ( composition . getSuffixChain ( ) , inferenceProducer , dispatcher ) ) for ( IndexedObjectProperty commonLeft : commonSubProperties ) saturation . leftSubComposableSubPropertiesByRightProperties . ( rightSubProperty , commonLeft ) ; } } saturation . leftSubComposableSubPropertiesByRightPropertiesComputed = true ; } return saturation . leftSubComposableSubPropertiesByRightProperties ; }
Given an {@link IndexedObjectProperty} Computes a {@link Multimap} from
{@link IndexedObjectProperty}s to {@link IndexedObjectProperty}
consisting of the the assignments T -> S such that both S and
ObjectPropertyChain(S, T) are sub-properties of the given
{@link IndexedObjectProperty}. The provided {@link Producer} is used to
record all {@link ObjectPropertyInference}s that are applied in this
computation of sub-{@link IndexedPropertyChain}s involved. It is ensured
that the computation is performed only once.

@param input
a given {@link IndexedObjectProperty}
@param inferenceProducer
@return a multimap consisting of assignments T -> S such that both S and
ObjectPropertyChain(S, T) are sub-properties of the given
{@link IndexedObjectProperty}
Given an { @link IndexedObjectProperty } Computes a { @link Multimap } from { @link IndexedObjectProperty } s to { @link IndexedObjectProperty } consisting of the the assignments T - > S such that both S and ObjectPropertyChain ( S T ) are sub - properties of the given { @link IndexedObjectProperty } . The provided { @link Producer } is used to record all { @link ObjectPropertyInference } s that are applied in this computation of sub - { @link IndexedPropertyChain } s involved . It is ensured that the computation is performed only once .