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

fr.boreal.model.logicalElements.impl.SubstitutionImpl Maven / Gradle / Ivy

The newest version!
package fr.boreal.model.logicalElements.impl;

import fr.boreal.model.logicalElements.api.*;

import java.io.Serial;
import java.io.Serializable;
import java.util.*;

/**
 * Default implementation of Substitution using a map
 *
 * @author Florent Tornil
 *
 */
public class SubstitutionImpl implements Substitution, Serializable {

	@Serial
	private static final long serialVersionUID = 8409744590170243850L;
	private final Map map;

	/////////////////////////////////////////////////
	// Constructors
	/////////////////////////////////////////////////

	/**
	 * Default constructor using a HashMap
	 */
	public SubstitutionImpl() {
		this.map = new HashMap<>();
	}

	/**
	 * Constructor using a user-given map
	 *
	 * @param associations a map representing a substitution
	 */
	public SubstitutionImpl(Map associations) {
		this.map = associations;
	}

	/**
	 * Copy contructor
	 *
	 * @param s another substitution
	 */
	public SubstitutionImpl(Substitution s) {
		this(new HashMap<>(s.keys().size()));
		for (Variable v : s.keys()) {
			this.add(v, s.createImageOf(v));
		}
	}

	/////////////////////////////////////////////////
	// Public methods
	/////////////////////////////////////////////////

	@Override
	public Term createImageOf(Term term) {
		Term substitut = null;
		if (term instanceof FunctionalTerm f) {
			substitut = f.eval(this);
		}

		if (term instanceof StoredFunctionalTerm f) {
			substitut = f.eval(this);
		}

		if (substitut == null) {
			substitut = this.map.get(term);
		}

		return (substitut == null) ? term : substitut;
	}

	@Override
	public Atom createImageOf(Atom atom) {
		Atom substitut = null;

		if (atom instanceof ComputedAtom) {
			substitut = ((ComputedAtom) atom).eval(this);
		}

		if (substitut == null) {
			List res = new ArrayList<>();
			for (int i = 0; i < atom.getPredicate().arity(); i++) {
				Term t = atom.getTerm(i);
				res.add(this.createImageOf(t));
			}
			substitut = new AtomImpl(atom.getPredicate(), res);
		}

		return substitut;
	}

	@Override
	public Collection keys() {
		return this.map.keySet();
	}

	@Override
	public void add(Variable v, Term t) {
		this.map.put(v, t);
	}

	@Override
	public void remove(Variable v) {
		this.map.remove(v);
	}

	@Override
	public boolean isEmpty() {
		return this.map.isEmpty();
	}

	@Override
	public Optional merged(Substitution other) {
		if (this.isEmpty()) {
			return Optional.of(other);
		}
		if (other.isEmpty()) {
			return Optional.of(this);
		}

		Substitution result = new SubstitutionImpl(this);
		for (Variable current_variable : other.keys()) {
			Term b_image = other.createImageOf(current_variable);
			if (result.keys().contains(current_variable)) {
				Term current_image = result.createImageOf(current_variable);
				if (!current_image.equals(b_image)) {
					return Optional.empty();
				}
			} else {
				result.add(current_variable, b_image);
			}
		}
		return Optional.of(result);
	}

	@Override
	public Optional aggregated(Substitution s) {
		SubstitutionImpl newSub = new SubstitutionImpl(this);
		for (Variable term : s.keys()) {
			if (!newSub.aggregate(term, s.createImageOf(term))) {
				return Optional.empty();
			}
		}
		return Optional.of(newSub);
	}

	private boolean aggregate(Variable term, Term substitut) {
		Term termSubstitut = this.createImageOf(term);
		Term substitutSubstitut = this.createImageOf(substitut);

		if (!termSubstitut.equals(substitutSubstitut)) {
			if (termSubstitut.isConstant()) {
				if (substitutSubstitut.isConstant()) {
					return substitutSubstitut.equals(termSubstitut);
				} else {
					Term tmp = termSubstitut;
					termSubstitut = substitutSubstitut;
					substitutSubstitut = tmp;
				}
			}

			for (Variable t : this.keys()) {
				Term image = this.createImageOf(t);
				if (termSubstitut.equals(image) && !t.equals(substitutSubstitut)) {
					this.add(t, substitutSubstitut);
				}
			}

			this.add((Variable) termSubstitut, substitutSubstitut);
		}
		return true;
	}

	@Override
	public Substitution limitedTo(Collection vars) {
		Substitution result = new SubstitutionImpl();
		for (Variable v : this.keys()) {
			if (vars.contains(v)) {
				result.add(v, this.createImageOf(v));
			}
		}
		return result;
	}

	@Override
	public boolean isExtensionOf(Substitution other) {
		Substitution limited_copy = this.limitedTo(other.keys());
		return limited_copy.equals(other);
	}

	@Override
	public boolean isInjective() {
		Set terms = new HashSet<>();
		for (Term value : map.values()) {
			if (terms.contains(value)) {
				return false;
			}
			terms.add(value);
		}

		return true;

	}

	@Override
	public boolean isInvertible() {
		for (Term value : map.values()) {
			if (value.isFrozen(null)) {
				return false;
			}
		}
		return isInjective();
	}

	@Override
	public Set rangeTerms() {
		Set imageTerms = new HashSet<>();
		for (Variable key : map.keySet()) {
			imageTerms.add(map.get(key));
		}
		return imageTerms;
	}

	@Override
	public Map toMap() {
		return this.map;
	}

	/////////////////////////////////////////////////
	// Object methods
	/////////////////////////////////////////////////

	@Override
	public int hashCode() {
		return this.map.hashCode();
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) {
			return true;
		} else if (o == null) {
			return false;
		} else if (o instanceof SubstitutionImpl) {
			return this.map.equals(((SubstitutionImpl) o).map);
		} else {
			return false;
		}
	}

	/**
	 * @return a string representation of this substitution of the form {v1:t1, ...,
	 *         vn:tn}
	 */
	@Override
	public String toString() {

		StringBuilder sb = new StringBuilder();
		sb.append("{");
		boolean first = true;
		for (Variable v : this.keys()) {
			if (!first) {
				sb.append(", ");
			}
			sb.append(v.toString());
			sb.append(":");
			sb.append(this.map.get(v));
			first = false;
		}
		sb.append("}");
		return sb.toString();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy