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

fr.boreal.model.formula.FOFormulas Maven / Gradle / Ivy

The newest version!
package fr.boreal.model.formula;

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Queue;
import java.util.Set;
import java.util.stream.Collectors;

import com.google.common.collect.Sets;

import fr.boreal.model.formula.api.*;
import fr.boreal.model.formula.factory.FOFormulaFactory;
import fr.boreal.model.logicalElements.api.Atom;
import fr.boreal.model.logicalElements.api.Substitution;
import fr.boreal.model.logicalElements.api.Term;
import fr.boreal.model.logicalElements.api.Variable;

/**
 * Utility class for standard operations on formulas
 * @author Florent Tornil
 *
 */
public class FOFormulas {

	private static final FOFormulaFactory formula_factory = FOFormulaFactory.instance();

	/**
	 * @param formula the formula
	 * @param s the substitution
	 * @return a new FOFormula corresponding to the given FOFormula in which the
	 *         given substitution have been applied
	 */
	public static  Formula createImageWith(Formula formula, Substitution s) {
		if (formula.isAtomic()) {
			Atom substituted_atom = s.createImageOf(((Atom) formula));
			return (Formula) substituted_atom;
		} else if (formula.isNegation()) {
			FOFormula new_element = FOFormulas.createImageWith(((FOFormulaNegation) formula).element(), s);
			return (Formula) formula_factory.createOrGetNegation(new_element);
		} else if (formula.isConjunction()) {
			Collection new_elements = ((FOFormulaConjunction) formula).getSubElements().stream()
					.map(f -> FOFormulas.createImageWith(f, s)).collect(Collectors.toSet());
			return (Formula) formula_factory.createOrGetConjunction(new_elements);
		} else if (formula.isDisjunction()) {
			Collection new_elements = ((FOFormulaDisjunction) formula).getSubElements().stream()
					.map(f -> FOFormulas.createImageWith(f, s)).collect(Collectors.toSet());
			return (Formula) formula_factory.createOrGetDisjunction(new_elements);
		} else {
			throw new IllegalArgumentException("Formula is neither atomic, conjunctive, disjunctive nor nagtive.");
		}
	}

	/**
	 * @param formula the formula
	 * @return all the terms of the given formula
	 */
	public static Collection getTerms(FOFormula formula) {
		if (formula.isAtomic()) {
			return Arrays.asList(((Atom) formula).getTerms());
		} else if (formula.isNegation()) {
			return FOFormulas.getTerms(((FOFormulaNegation) formula).element());
		} else if (formula.isConjunction()) {
			return ((FOFormulaConjunction) formula).getSubElements().stream().map(FOFormulas::getTerms)
					.flatMap(Collection::stream).collect(Collectors.toSet());
		} else if (formula.isDisjunction()) {
			return ((FOFormulaDisjunction) formula).getSubElements().stream().map(FOFormulas::getTerms)
					.flatMap(Collection::stream).collect(Collectors.toSet());
		}
		return Collections.emptySet();
	}

	/**
	 * @param formula the atoms to order which may be compatible with flatten
	 * @return all the atoms in the given formula in an order avoiding cartesian products when possible
	 */
	public static LinkedHashSet getOrderedAtoms(FOFormula formula) {
		Set atoms = formula.asAtomSet();
		LinkedHashSet result = new LinkedHashSet<>();
		Queue toCheck = new ArrayDeque<>();
		while (!atoms.isEmpty()) {
			Iterator atomsIt = atoms.iterator();
			Atom atom1;
			if(toCheck.isEmpty()) {
				atom1 = atomsIt.next();
				atomsIt.remove();
			} else {
				atom1 = toCheck.poll();
			}
			result.add(atom1);
			while (atomsIt.hasNext()) {
				Atom atom2 = atomsIt.next();
				for (Variable v : atom2.getVariables()) {
					if (atom1.getVariables().contains(v)) {
						boolean alreadySeen = result.add(atom2);
						if(!alreadySeen) {
							toCheck.add(atom2);
						}
						atomsIt.remove();
						toCheck.add(atom2);
						break;
					}
				}
			}
		}
		return result;
	}

	/**
	 * @param formula the atoms to compute join variables on, which may be compatible with flatten
	 * @return all the variables that are used in at least 2 atoms of the formula
	 */
	public static Set getJoinVariables(FOFormula formula) {
		Set atoms = formula.asAtomSet();
		Set joinVariables = new HashSet<>();
		Set seen = new HashSet<>();
		for(Atom a : atoms) {
			Set aVariables = a.getVariables();
			joinVariables.addAll(Sets.intersection(seen, aVariables));
			seen.addAll(aVariables);
		}
		return joinVariables;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy