fr.boreal.forward_chaining.chase.ChaseBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of integraal-forward-chaining Show documentation
Show all versions of integraal-forward-chaining Show documentation
InteGraal forward chaining algorithms
The newest version!
package fr.boreal.forward_chaining.chase;
import fr.boreal.forward_chaining.chase.halting_condition.CreatedFactsAtPreviousStep;
import fr.boreal.forward_chaining.chase.halting_condition.HaltingCondition;
import fr.boreal.forward_chaining.chase.halting_condition.HasRulesToApply;
import fr.boreal.forward_chaining.chase.rule_applier.BreadthFirstTriggerRuleApplier;
import fr.boreal.forward_chaining.chase.rule_applier.ParallelTriggerRuleApplier;
import fr.boreal.forward_chaining.chase.rule_applier.RuleApplier;
import fr.boreal.forward_chaining.chase.rule_applier.SourceDelegatedDatalogRuleApplier;
import fr.boreal.forward_chaining.chase.rule_applier.body_to_query_transformer.AllTransformer;
import fr.boreal.forward_chaining.chase.rule_applier.body_to_query_transformer.BodyToQueryTransformer;
import fr.boreal.forward_chaining.chase.rule_applier.body_to_query_transformer.FrontierTransformer;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.TriggerApplier;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.TriggerApplierImpl;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.facts_handler.DelegatedApplication;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.facts_handler.DirectApplication;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.facts_handler.FactsHandler;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_applier.renamer.*;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_checker.*;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_computer.NaiveTriggerComputer;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_computer.SemiNaiveComputer;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_computer.TriggerComputer;
import fr.boreal.forward_chaining.chase.rule_applier.trigger_computer.TwoStepComputer;
import fr.boreal.forward_chaining.chase.rule_scheduler.GRDScheduler;
import fr.boreal.forward_chaining.chase.rule_scheduler.NaiveScheduler;
import fr.boreal.forward_chaining.chase.rule_scheduler.RuleScheduler;
import fr.boreal.forward_chaining.chase.treatment.AddCreatedFacts;
import fr.boreal.forward_chaining.chase.treatment.Debug;
import fr.boreal.forward_chaining.chase.treatment.EndTreatment;
import fr.boreal.forward_chaining.chase.treatment.Pretreatment;
import fr.boreal.model.formula.api.FOFormula;
import fr.boreal.model.kb.api.FactBase;
import fr.boreal.model.kb.api.RuleBase;
import fr.boreal.model.logicalElements.factory.api.TermFactory;
import fr.boreal.model.logicalElements.factory.impl.FactoryConstants;
import fr.boreal.model.queryEvaluation.api.FOQueryEvaluator;
import fr.boreal.query_evaluation.generic.FOQueryEvaluatorWithDBMSDelegation;
import fr.boreal.query_evaluation.generic.GenericFOQueryEvaluator;
import java.util.*;
/**
* @author Florent Tornil
*
* Builder to create a parameterized chase algorithm
*/
public class ChaseBuilder {
private FactBase fb;
private RuleBase rb;
private TermFactory tf = FactoryConstants.DEFAULT_TERM_FACTORY;
private RuleScheduler rsc;
private Scheduler scheduler = Scheduler.GRD;
private enum Scheduler {NAIVE, GRD}
private FOQueryEvaluator eval;
private Evaluator evaluator = Evaluator.GENERIC;
private enum Evaluator {GENERIC, SMART}
private RuleApplier ra;
private Applier applier = Applier.BREADTH_FIRST_TRIGGER;
private enum Applier {BREADTH_FIRST_TRIGGER, PARALLEL_TRIGGER, SOURCE_DELEGATED_DATALOG}
private BodyToQueryTransformer transf;
private Transformer transformer = Transformer.FRONTIER;
private enum Transformer {ALL, FRONTIER}
private TriggerComputer tc;
private Computer computer = Computer.SEMI_NAIVE;
private enum Computer {NAIVE, SEMI_NAIVE, TWO_STEP}
private TriggerChecker tch;
private Checker checker = Checker.SEMI_OBLIVIOUS;
private enum Checker {TRUE, OBLIVIOUS, SEMI_OBLIVIOUS, RESTRICTED, EQUIVALENT}
private TriggerApplier ta;
private FactsHandler fh;
private Application application = Application.DIRECT;
private enum Application {DIRECT, PARALLEL}
private TriggerRenamer renamer;
private Skolem skolem = Skolem.FRESH;
private enum Skolem {FRESH, BODY, FRONTIER, FRONTIER_PIECE}
private final List hcs = new ArrayList<>();
private final List global_pts = new ArrayList<>();
private final List step_pts = new ArrayList<>();
private final List global_end_ts = new ArrayList<>();
private final List end_step_ts = new ArrayList<>();
private boolean debug = false;
///////////
// Build //
///////////
/**
* The minimal configuration requires :
* * a FactBase to saturate
* * a RuleBase to get Rules from
* * a TermFactory to create new terms
*
* Default behavior is :
* * a GRDScheduler for rules
* * a TriggerRuleApplier with :
* * * a SemiNaiveTriggerComputer with a default GenericFOQueryEvaluator
* * * a SemiObliviousChecker
* * * a Applier with :
* * * * a FreshRenamer
* * * * a DirectApplication
* * HaltingConditions :
* * * CreatedFactsAtPreviousStep
* * * HasRulesToApply
*
* @return the created chase or an empty optional if the configuration is incorrect
*/
public Optional build() {
if(this.getMinimalConfig().isPresent()) {
return Optional.of(new ChaseImpl(fb, rb, rsc, ra, hcs, global_pts, step_pts, global_end_ts, end_step_ts));
} else {
return Optional.empty();
}
}
////////////////////
// Default chases //
////////////////////
/**
* Builder initialized with the default chase and mandatory parameters
* @param fb the factbase to saturate
* @param rb the rule to apply
* @return the builder initialized with the given parameters
*/
public static ChaseBuilder defaultBuilder(FactBase fb, RuleBase rb) {
return new ChaseBuilder()
.setFactBase(fb)
.setRuleBase(rb);
}
/**
* Chase initialized with the default parameters and the given mandatory parameters
* @param fb the factbase to saturate
* @param rb the rule to apply
* @return the default chase initialized with the given parameters
*/
public static Chase defaultChase(FactBase fb, RuleBase rb) {
return new ChaseBuilder()
.setFactBase(fb)
.setRuleBase(rb)
.build()
.get();
}
//////////////////////
// Default settings //
//////////////////////
private Optional getMinimalConfig() {
if(this.fb == null) {
return Optional.empty();
}
if(this.rb == null) {
return Optional.empty();
}
if(this.tf == null) {
return Optional.empty();
}
if(this.rsc == null) {
switch (this.scheduler) {
case NAIVE : this.setRuleScheduler(new NaiveScheduler(this.rb)); break;
case GRD : this.setRuleScheduler(new GRDScheduler(this.rb)); break;
}
}
if(this.eval == null) {
switch (this.evaluator) {
case GENERIC : this.setFOQueryEvaluator(GenericFOQueryEvaluator.defaultInstance()); break;
case SMART : this.setFOQueryEvaluator(FOQueryEvaluatorWithDBMSDelegation.defaultInstance()); break;
}
}
if(this.ra == null) {
switch(this.applier) {
case BREADTH_FIRST_TRIGGER : case PARALLEL_TRIGGER : {
if(this.transf == null) {
switch (this.transformer) {
case ALL : this.setBodyToQueryTransformer(new AllTransformer()); break;
case FRONTIER : this.setBodyToQueryTransformer(new FrontierTransformer()); break;
}
}
if(this.tc == null) {
switch (this.computer) {
case NAIVE : this.setTriggerComputer(new NaiveTriggerComputer(this.eval)); break;
case SEMI_NAIVE : this.setTriggerComputer(new SemiNaiveComputer(this.eval)); break;
case TWO_STEP : this.setTriggerComputer(new TwoStepComputer(this.eval)); break;
}
}
if(this.tch == null) {
switch (this.checker) {
case TRUE : this.setTriggerChecker(new AlwaysTrueChecker()); break;
case OBLIVIOUS : this.setTriggerChecker(new ObliviousChecker()); break;
case SEMI_OBLIVIOUS : this.setTriggerChecker(new SemiObliviousChecker()); break;
case RESTRICTED : this.setTriggerChecker(new RestrictedChecker(this.eval)); break;
case EQUIVALENT : this.setTriggerChecker(new EquivalentChecker(this.eval)); break;
}
}
if(this.ta == null) {
if(this.renamer == null) {
switch (this.skolem) {
case FRESH : this.setExistentialsRenamer(new FreshRenamer(this.tf)); break;
case BODY : this.setExistentialsRenamer(new BodySkolem(this.tf)); break;
case FRONTIER : this.setExistentialsRenamer(new FrontierSkolem(this.tf)); break;
case FRONTIER_PIECE : this.setExistentialsRenamer(new FrontierByPieceSkolem(this.tf)); break;
}
}
if(this.fh == null) {
switch(this.application) {
case DIRECT : this.setNewFactsHandler(new DirectApplication()); break;
case PARALLEL : this.setNewFactsHandler(new DelegatedApplication()); break;
}
}
this.setTriggerApplier(new TriggerApplierImpl(this.renamer, this.fh));
}
break;
}
case SOURCE_DELEGATED_DATALOG: // do nothing
break;
}
switch(this.applier) {
case BREADTH_FIRST_TRIGGER : this.setRuleApplier(new BreadthFirstTriggerRuleApplier(this.transf, this.tc, this.tch, this.ta)); break;
case PARALLEL_TRIGGER : this.setRuleApplier(new ParallelTriggerRuleApplier(this.transf, this.tc, this.tch, this.ta)); break;
case SOURCE_DELEGATED_DATALOG : this.setRuleApplier(new SourceDelegatedDatalogRuleApplier()); break;
}
}
if(this.hcs.isEmpty()) {
this.addStandardHaltingConditions();
}
if(this.application == Application.PARALLEL) {
this.end_step_ts.addFirst(new AddCreatedFacts());
}
if(this.debug) {
this.addStepEndTreatments(new Debug());
}
return Optional.of(this);
}
///////////////////////////
// Higher level settings //
///////////////////////////
// Rule Applier //
/**
* Use a breadth first trigger applier
* @return this
*/
public ChaseBuilder useTriggerRuleApplier() {
this.applier = Applier.BREADTH_FIRST_TRIGGER;
return this;
}
// FOQuery Evaluator //
/**
* Use the generic query evaluator
* @return this
*/
public ChaseBuilder useGenericFOQueryEvaluator() {
this.evaluator = Evaluator.GENERIC;
return this;
}
/**
* Use the smart query evaluator
* @return this
*/
public ChaseBuilder useSmartFOQueryEvaluator() {
this.evaluator = Evaluator.SMART;
return this;
}
// Scheduler //
/**
* Use a naive rule scheduler
* @return this
*/
public ChaseBuilder useNaiveRuleScheduler() {
this.scheduler = Scheduler.NAIVE;
return this;
}
/**
* Use a rule scheduler based on the GRD
* @return this
*/
public ChaseBuilder useGRDRuleScheduler() {
this.scheduler = Scheduler.GRD;
return this;
}
// Body To Query transformers //
/**
* Use a transformation that keep all variables as answer variables when evaluating a rule's body
* @return this
*/
public ChaseBuilder useAllTransformer() {
this.transformer = Transformer.ALL;
return this;
}
/**
* Use a transformation that keep only the variables of the frontier as answer variables when evaluating a rule's body
* @return this
*/
public ChaseBuilder useFrontierTransformer() {
this.transformer = Transformer.FRONTIER;
return this;
}
// Computer //
/**
* Use a naive method to compute triggers
* @return this
*/
public ChaseBuilder useNaiveComputer() {
this.computer = Computer.NAIVE;
return this;
}
/**
* Use the semi naive method to compute triggers
* @return this
*/
public ChaseBuilder useSemiNaiveComputer() {
this.computer = Computer.SEMI_NAIVE;
return this;
}
/**
* Use the two step method to compute triggers
* @return this
*/
public ChaseBuilder useTwoStepComputer() {
this.computer = Computer.TWO_STEP;
return this;
}
// Application //
/**
* Use a direct application of the triggers
* @return this
*/
public ChaseBuilder useDirectApplication() {
this.application = Application.DIRECT;
this.applier = Applier.BREADTH_FIRST_TRIGGER;
return this;
}
/**
* Use a parallel application of the triggers
* @return this
*/
public ChaseBuilder useParallelApplication() {
this.application = Application.PARALLEL;
this.applier = Applier.PARALLEL_TRIGGER;
return this;
}
/**
* Use a method of delegating to the source the application of the datalog rules
* @return this
*/
public ChaseBuilder useSourceDelegatedDatalogApplication() {
this.applier = Applier.SOURCE_DELEGATED_DATALOG;
return this;
}
// Criteria //
/**
* Use an always true criteria for the triggers
* @return this
*/
public ChaseBuilder useAlwaysTrueChecker() {
this.checker = Checker.TRUE;
return this;
}
/**
* Use a oblivious criteria for the triggers
* @return this
*/
public ChaseBuilder useObliviousChecker() {
this.checker = Checker.OBLIVIOUS;
return this;
}
/**
* Use a semi oblivious criteria for the triggers
* @return this
*/
public ChaseBuilder useSemiObliviousChecker() {
this.checker = Checker.SEMI_OBLIVIOUS;
return this;
}
/**
* Use a restricted criteria for the triggers
* @return this
*/
public ChaseBuilder useRestrictedChecker() {
this.checker = Checker.RESTRICTED;
return this;
}
/**
* Use an equivalent criteria for the triggers
* @return this
*/
public ChaseBuilder useEquivalentChecker() {
this.checker = Checker.EQUIVALENT;
return this;
}
// Existentials naming //
/**
* Use a fresh name for the existentials
* @return this
*/
public ChaseBuilder useFreshNaming() {
this.skolem = Skolem.FRESH;
return this;
}
/**
* Use a skolem of the body as name for the existentials
* @return this
*/
public ChaseBuilder useBodySkolem() {
this.skolem = Skolem.BODY;
return this;
}
/**
* Use a skolem of the body, limited to the frontier as name for the existentials
* @return this
*/
public ChaseBuilder useFrontierSkolem() {
this.skolem = Skolem.FRONTIER;
return this;
}
/**
* Use a skolem of the body, limited to the frontier of the piece as name for the existentials
* @return this
*/
public ChaseBuilder useFrontierByPieceSkolem() {
this.skolem = Skolem.FRONTIER_PIECE;
return this;
}
/////////////
// Setters //
/////////////
/**
* Sets the FactBase
* @param fb the FactBase
* @return this
*/
public ChaseBuilder setFactBase(FactBase fb) {
this.fb = fb;
return this;
}
/**
* Sets the RuleBase
* @param rb the RuleBase
* @return this
*/
public ChaseBuilder setRuleBase(RuleBase rb) {
this.rb = rb;
return this;
}
/**
* Sets the TermFactory
* @param tf the TermFactory
* @return this
*/
public ChaseBuilder setTermFactory(TermFactory tf) {
this.tf = tf;
return this;
}
/**
* Sets the RuleScheduler
* @param rsc the RuleScheduler
* @return this
*/
public ChaseBuilder setRuleScheduler(RuleScheduler rsc) {
this.rsc = rsc;
return this;
}
/**
* Sets the FOQueryEvaluator
* @param eval the FOQueryEvaluator
* @return this
*/
public ChaseBuilder setFOQueryEvaluator(FOQueryEvaluator eval) {
this.eval = eval;
return this;
}
/**
* Sets the RuleApplier
* @param ra the RuleApplier
* @return this
*/
public ChaseBuilder setRuleApplier(RuleApplier ra) {
this.ra = ra;
return this;
}
// Triggers
/**
* Sets the BodyToQueryTransformer
* @param transf the BodyToQueryTransformer
* @return this
*/
public ChaseBuilder setBodyToQueryTransformer(BodyToQueryTransformer transf) {
this.transf = transf;
return this;
}
/**
* Sets the TriggerComputer
* @param tc the TriggerComputer
* @return this
*/
public ChaseBuilder setTriggerComputer(TriggerComputer tc) {
this.tc = tc;
return this;
}
/**
* Sets the TriggerChecker
* @param tch the TriggerChecker
* @return this
*/
public ChaseBuilder setTriggerChecker(TriggerChecker tch) {
this.tch = tch;
return this;
}
/**
* Sets the TriggerApplier
* @param ta the TriggerApplier
* @return this
*/
public ChaseBuilder setTriggerApplier(TriggerApplier ta) {
this.ta = ta;
return this;
}
/**
* Sets the TriggerRenamer
* @param tr the TriggerRenamer
* @return this
*/
public ChaseBuilder setExistentialsRenamer(TriggerRenamer tr) {
this.renamer = tr;
return this;
}
/**
* Sets the FactsHandler
* @param fh the FactsHandler
* @return this
*/
public ChaseBuilder setNewFactsHandler(FactsHandler fh) {
this.fh = fh;
return this;
}
// halting conditions
/**
* Adds the standard halting conditions
* @return this
*/
public ChaseBuilder addStandardHaltingConditions() {
this.addHaltingConditions(new CreatedFactsAtPreviousStep(), new HasRulesToApply());
return this;
}
/**
* Adds the given halting conditions
* @param hcs halting conditions
* @return this
*/
public ChaseBuilder addHaltingConditions(HaltingCondition... hcs) {
this.hcs.addAll(Arrays.asList(hcs));
return this;
}
/**
* Adds the given halting conditions
* @param hcs halting conditions
* @return this
*/
public ChaseBuilder addHaltingConditions(Collection hcs) {
this.hcs.addAll(hcs);
return this;
}
// Global pretreatment
/**
* Adds the given Global pretreatment
* @param pts Global pretreatment
* @return this
*/
public ChaseBuilder addGlobalPretreatments(Pretreatment... pts) {
this.global_pts.addAll(Arrays.asList(pts));
return this;
}
/**
* Adds the given Global pretreatment
* @param pts Global pretreatment
* @return this
*/
public ChaseBuilder addGlobalPretreatments(Collection pts) {
this.global_pts.addAll(pts);
return this;
}
// Step pretreament
/**
* Adds the given Step pretreatment
* @param pts Step pretreatment
* @return this
*/
public ChaseBuilder addStepPretreatments(Pretreatment... pts) {
this.step_pts.addAll(Arrays.asList(pts));
return this;
}
/**
* Adds the given Step pretreatment
* @param pts Step pretreatment
* @return this
*/
public ChaseBuilder addStepPretreatments(Collection pts) {
this.step_pts.addAll(pts);
return this;
}
// Global end treatement
/**
* Adds the given Global end treatement
* @param ets Step Global end treatement
* @return this
*/
public ChaseBuilder addGlobalEndTreatments(EndTreatment... ets) {
this.global_end_ts.addAll(Arrays.asList(ets));
return this;
}
/**
* Adds the given Global end treatement
* @param ets Step Global end treatement
* @return this
*/
public ChaseBuilder addGlobalEndTreatments(Collection ets) {
this.global_end_ts.addAll(ets);
return this;
}
// Step end treatement
/**
* Adds the given Step end treatement
* @param ets Step end treatement
* @return this
*/
public ChaseBuilder addStepEndTreatments(EndTreatment... ets) {
this.end_step_ts.addAll(Arrays.asList(ets));
return this;
}
/**
* Adds the given Step end treatement
* @param ets Step end treatement
* @return this
*/
public ChaseBuilder addStepEndTreatments(Collection ets) {
this.end_step_ts.addAll(ets);
return this;
}
/**
* Adds the debug option
* @return this
*/
public ChaseBuilder debug() {
this.debug = true;
return this;
}
}