
it.unibz.inf.ontop.substitution.impl.AbstractSubstitutionOperations Maven / Gradle / Ivy
package it.unibz.inf.ontop.substitution.impl;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import it.unibz.inf.ontop.exception.MinorOntopInternalBugException;
import it.unibz.inf.ontop.iq.node.ExtensionalDataNode;
import it.unibz.inf.ontop.model.term.*;
import it.unibz.inf.ontop.model.term.functionsymbol.BooleanFunctionSymbol;
import it.unibz.inf.ontop.substitution.Substitution;
import it.unibz.inf.ontop.substitution.SubstitutionOperations;
import it.unibz.inf.ontop.substitution.UnifierBuilder;
import it.unibz.inf.ontop.utils.ImmutableCollectors;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collector;
public abstract class AbstractSubstitutionOperations extends AbstractSubstitutionBasicOperations implements SubstitutionOperations {
private final Function typeCast;
private final Function, Substitution extends T>> substitutionTypeCast;
private final Function, T> keyMapper;
/**
* @param typeCast effectively ensures that Variable is a subtype of T (normally, it's simply v -> v)
* @param substitutionTypeCast effectively ensures that Variable is a subtype of T (normally, it's simply s -> s)
*/
AbstractSubstitutionOperations(TermFactory termFactory,
Function typeCast,
Function, Substitution extends T>> substitutionTypeCast) {
super(termFactory);
this.typeCast = typeCast;
this.substitutionTypeCast = substitutionTypeCast;
this.keyMapper = e -> typeCast.apply(e.getKey());
}
@Override
public T apply(Substitution extends T> substitution, Variable variable) {
return applyToVariable(substitution, variable, typeCast);
}
@Override
public ImmutableFunctionalTerm apply(Substitution extends T> substitution, ImmutableFunctionalTerm term) {
if (term.getFunctionSymbol() instanceof BooleanFunctionSymbol)
return apply(substitution, (ImmutableExpression)term);
if (substitution.isEmpty())
return term;
return termFactory.getImmutableFunctionalTerm(term.getFunctionSymbol(), substitution.applyToTerms(term.getTerms()));
}
@Override
public ImmutableExpression apply(Substitution extends T> substitution, ImmutableExpression expression) {
if (substitution.isEmpty())
return expression;
return termFactory.getImmutableExpression(expression.getFunctionSymbol(), substitution.applyToTerms(expression.getTerms()));
}
@Override
public ImmutableList apply(Substitution extends T> substitution, ImmutableList extends Variable> variables) {
return variables.stream()
.map(v -> apply(substitution, v))
.collect(ImmutableCollectors.toList());
}
@Override
public ImmutableSet apply(Substitution extends T> substitution, ImmutableSet extends Variable> terms) {
return terms.stream()
.map(v -> apply(substitution, v))
.collect(ImmutableCollectors.toSet());
}
@Override
public T rename(Substitution renaming, T t) {
return applyToTerm(substitutionTypeCast.apply(renaming), t);
}
protected Substitution emptySubstitution() {
return termFactory.getSubstitution(ImmutableMap.of());
}
@Override
public AbstractUnifierBuilder unifierBuilder() {
return unifierBuilder(emptySubstitution());
}
@Override // ensures that there is no cast in toUnifier()
public abstract AbstractUnifierBuilder unifierBuilder(Substitution substitution);
@Override
public Collector, ?, Optional>> toUnifier() {
return Collector.of(
this::unifierBuilder,
(a, s) -> a.unify(s.stream(), keyMapper, Map.Entry::getValue),
AbstractUnifierBuilder::merge,
UnifierBuilder::build);
}
private static final class ArgumentMapUnifierImpl implements ArgumentMapUnifier {
private final ImmutableMap argumentMap;
private final Substitution substitution;
ArgumentMapUnifierImpl(ImmutableMap argumentMap, Substitution substitution) {
this.argumentMap = argumentMap;
this.substitution = substitution;
}
@Override
public ImmutableMap getArgumentMap() {
return argumentMap;
}
@Override
public Substitution getSubstitution() {
return substitution;
}
@Override
public String toString() { return argumentMap + " with " + substitution; }
}
private final class ArgumentMapUnifierBuilder {
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
private Optional> optional;
ArgumentMapUnifierBuilder() {
optional = Optional.of(new ArgumentMapUnifierImpl<>(ImmutableMap.of(), emptySubstitution()));
}
void unify(ImmutableMap argumentMap) {
if (optional.isEmpty())
return;
ArgumentMapUnifier unifier = optional.get();
ImmutableMap updatedArgumentMap = applyToTerms(unifier.getSubstitution(), argumentMap);
Optional> optionalUpdatedSubstitution = unifierBuilder()
.unify(
Sets.intersection(unifier.getArgumentMap().keySet(), updatedArgumentMap.keySet()).stream(),
unifier.getArgumentMap()::get,
updatedArgumentMap::get)
.build();
optional = optionalUpdatedSubstitution
.flatMap(u -> unifierBuilder(unifier.getSubstitution())
.unify(u.stream(), keyMapper, Map.Entry::getValue)
.build()
.map(s -> new ArgumentMapUnifierImpl<>(
applyToTerms(u, ExtensionalDataNode.union(unifier.getArgumentMap(), updatedArgumentMap)),
s)));
}
ArgumentMapUnifierBuilder merge(ArgumentMapUnifierBuilder another) {
throw new MinorOntopInternalBugException("Not expected to be run in parallel");
}
Optional> build() {
return optional;
}
}
@Override
public Collector, ?, Optional>> toArgumentMapUnifier() {
return Collector.of(ArgumentMapUnifierBuilder::new, ArgumentMapUnifierBuilder::unify, ArgumentMapUnifierBuilder::merge, ArgumentMapUnifierBuilder::build);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy