fr.boreal.model.logicalElements.api.Substitution Maven / Gradle / Ivy
The newest version!
package fr.boreal.model.logicalElements.api;
import java.util.*;
/**
* A substitution is an application from a set of variables into a set of terms.
*
* @author Florent Tornil
*
*/
public interface Substitution {
/**
* Get the image of the given term by this substitution, if there is no image
* specified return the term itself.
*
* @param term a term
* @return the image of the specified term.
*/
Term createImageOf(Term term);
/**
* Get the domain of this substitution.
*
* @return the domain of this substitution.
*/
Collection keys();
/**
* Adds a mapping from the specified variable into the specified image to this
* substitution.
*
* @param v the key
* @param t the image
*
*/
void add(Variable v, Term t);
/**
* Apply this substitution on an atom.
*
* @param atom an atom
* @return an Atom which is the image of specified one by this substitution.
*/
Atom createImageOf(Atom atom);
/**
* Two substitutions can be merged iff for each key in common, the image is the
* same
*
* @param other a substitution
* @return a new substitution being the merge of this one and the other one or
* an empty optional if the substitutions are not compatible
*/
Optional merged(Substitution other);
/**
* @param vars variables to limit to
* @return a new substitution identical to this one but limited to a subset of
* variables
*/
Substitution limitedTo(Collection vars);
/**
* @param other a substitution
* @return true iff the other substitution is included into this one
*/
boolean isExtensionOf(Substitution other);
/**
* The aggregation of a substitution is more complex that just add a new
* mapping for a new variable. Especially, it does not conserve the domain and
* codomain. It chooses a representative term for each connected component by
* successive application of the mapping. For example, if the current
* substitution is {X -> Y, Z -> U} and you add a mapping {Y -> 'a', Z -> V},
* the result is {Y -> 'a', X -> 'a', Z -> V, U -> V} or {Y -> 'a', X -> 'a', U
* -> Z, V -> Z} or {Y -> 'a', X -> 'a', Z -> U, V -> U}.
*
* @param s the substitution to aggregate with
* @return the aggregated substitution or an empty optional if it is not
* possible
*/
Optional aggregated(Substitution s);
/**
* Remove the given variable affectation from this substitution
*
* @param v a variable
*/
void remove(Variable v);
/**
* @return true iff this substitution is empty
*/
boolean isEmpty();
/**
*
* @return true if the image of variables in this substitution are constants
*/
default boolean mapsToConstantsOnly() {
return keys().stream().allMatch(variable -> createImageOf(variable).isFrozen(null));
}
/**
*
* @param variableSet of variables which must map to constants only
* @return true if the image of variables in this substitution are constants
*/
default boolean mapsToConstantsOnly(Collection variableSet) {
return keys().stream()
.allMatch(variable -> (!variableSet.contains(variable)) || createImageOf(variable).isFrozen(null));
}
/**
* @return true iff this substitution is injective
*/
boolean isInjective();
/**
* @return true iff the inverse of this substitution is a substitution
*/
boolean isInvertible();
/**
* @return all range term of the substitution
*/
Set rangeTerms();
/**
* Remove the variables that are sent into themselves
*/
default void removeIdentity() {
new ArrayList<>(this.keys()).stream().filter(v -> v.equals(this.createImageOf(v))).forEach(this::remove);
}
/**
* Convert the substitution to a map
* @return A map that represents the substitution
*/
Map toMap();
}