fr.boreal.backward_chaining.unfolding.UCQUnfolder Maven / Gradle / Ivy
package fr.boreal.backward_chaining.unfolding;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import fr.boreal.model.formula.api.FOFormula;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.collect.Sets;
import fr.boreal.backward_chaining.core.QueryCoreProcessorImpl;
import fr.boreal.backward_chaining.core.QueryCoreProcessor;
import fr.boreal.backward_chaining.cover.CoverFunction;
import fr.boreal.backward_chaining.cover.QueryCover;
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.impl.SubstitutionImpl;
import fr.boreal.model.query.api.FOQuery;
import fr.boreal.model.query.factory.FOQueryFactory;
import fr.boreal.model.ruleCompilation.api.RuleCompilation;
/**
* @author Florent Tornil
*
* Unfold an pivotal-UCQ into a classical UCQ
*/
public class UCQUnfolder {
private final RuleCompilation compilation;
private final CoverFunction coverFct;
private final QueryCoreProcessor core;
/**
* Creates a new UCQUnfolder using the given parameters
* @param compilation the rule compilation to use
*/
public UCQUnfolder(RuleCompilation compilation) {
this(new QueryCover(), new QueryCoreProcessorImpl(), compilation);
}
/**
* Creates a new UCQUnfolder using the given parameters
* @param coverFct the cover function to use
* @param core the core function to use
* @param compilation the rule compilation to use
*/
public UCQUnfolder(CoverFunction coverFct, QueryCoreProcessor core, RuleCompilation compilation) {
this.coverFct = coverFct;
this.core = core;
this.compilation = compilation;
}
/**
* Each query of the UCQ will be a core
* Computes a cover of the unfolding before returning it
* @param pivotalQueries a pivotal query
* @return the unfolding of the pivotal query by the compilation
*/
public Set> unfold(Collection> pivotalQueries) {
Set> unfoldedUCQ = new HashSet<>();
for(FOQuery extends FOFormula> pivotalQuery : pivotalQueries) {
List>> atomicUnfoldings = new ArrayList<>();
for(Atom a : pivotalQuery.getFormula().asAtomSet()) {
atomicUnfoldings.add(compilation.unfold(a));
}
Set>> unfolding = Sets.cartesianProduct(atomicUnfoldings);
for(List> atoms : unfolding) {
Set queryAtoms = new HashSet<>();
Substitution initialSubstitution = new SubstitutionImpl();
boolean valid = true;
for(Pair pair : atoms) {
if(valid) {
queryAtoms.add(pair.getKey());
Optional initialSubstitutionOpt = initialSubstitution.merged(pair.getValue());
if(initialSubstitutionOpt.isPresent()) {
initialSubstitution = initialSubstitutionOpt.get();
} else {
valid = false;
}
}
}
if(valid) {
FOQuery extends FOFormula> q = FOQueryFactory.instance().createOrGetQuery(
FOFormulaFactory.instance().createOrGetConjunction(queryAtoms.toArray(new Atom[0])),
pivotalQuery.getAnswerVariables());
q = this.core.computeCore(q);
unfoldedUCQ.add(q);
}
}
}
unfoldedUCQ = this.coverFct.cover(unfoldedUCQ);
return unfoldedUCQ;
}
}