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;
}
}