How to choose a reasoning engine#
This guide shows you how to pick and configure the engine that evaluates a rule, when the default boolean answer is not enough and you need a probabilistic or possibilistic verdict instead.
You select the engine on the call, not on the graph: every fg.eval.evaluate(...) and fg.eval.explain(...) call takes an engine= keyword, and the probabilistic and possibilistic engines additionally take a config= wrapper. The same rule and the same facts can be evaluated under any supported engine.
Prerequisites#
- A
FactGraphwith a schema and facts (see How to write and read facts). - A rule or
RuleExprto evaluate (see How to evaluate a rule and read the proof). - For any engine other than
native, the matching adapter package must be importable. The non-native engines are registered by importing their adapter package; until then the engine name is rejected at evaluation time with the message<engine> evaluator not registered; import factgraph.adapters.<engine> first.
Decide which engine you need#
The accepted engine names are fixed: native, souffle, problog, pyreason. Pick by the kind of answer you want back on each row’s certainty:
native(the default whenengine=is omitted): boolean derivation. Use it for plain “does this hold” questions.souffle: boolean derivation evaluated through the Souffle Datalog adapter. Same boolean verdict as native, different backend.problog: probabilistic derivation. Each row carries a probability. Use it when facts or branches have probabilities attached.pyreason: possibilistic derivation over time. Each row carries a[lower, upper]interval. Use it for interval-bounded, temporal reasoning.
Only problog and pyreason consume a config=. Passing config= to native or souffle is rejected.
Steps#
Run with the default engine to get a boolean answer. Omitting
engine=resolves tonative:result = fg.eval.evaluate(rule, head=rule) row = result[0] row.certainty.kind # "boolean"To use the Souffle backend instead, import its adapter once, then pass
engine="souffle":import factgraph.adapters.souffle # registers the "souffle" evaluator result = fg.eval.evaluate(rule, head=rule, engine="souffle")For a probabilistic answer, import the ProbLog adapter and pass
engine="problog":import factgraph.adapters.problog # registers the "problog" evaluator result = fg.eval.evaluate(rule, head=rule, engine="problog") result[0].certainty.kind # "probabilistic"To attach branch probabilities, pass a
ProbLogConfigasconfig=instead ofengine=. The SDK derivesengine="problog"from the wrapper, so you do not need both:from factgraph.sdk import ProbLogConfig expr = left.as_("left") | right.as_("right") result = fg.eval.evaluate( expr, head=left, config=ProbLogConfig(case_probabilities={"left": 0.7}), )case_probabilitieskeys are branch ids and the values must be in(0, 1]. For a single rule (not aRuleExpr), branch-specificcase_probabilitiesare rejected; pass a bareProbLogConfig()or userule_paramskeyed by the rule’sid.For a possibilistic, time-aware answer, import the PyReason adapter and either pass
engine="pyreason"or aPyReasonConfigasconfig=:import factgraph.adapters.pyreason # registers the "pyreason" evaluator from factgraph.sdk import PyReasonConfig result = fg.eval.evaluate( rule, head=rule, config=PyReasonConfig(timestep_delay=0, iteration_count=1), ) result[0].certainty.kind # "possibilistic"PyReasonConfigcarries the time and interval settings:timestep_delay(>= 0),iteration_count(>= 1), and optional[lower, upper]interval bounds (derived_bound,head_bound,atom_bounds,case_bounds).derived_boundandhead_boundcannot both be set.If you want both
engine=andconfig=to be explicit, they must agree. Settingengine="problog"with aPyReasonConfig(or vice versa) raisesSDKStoreErrorbecause the wrapper’s engine does not matchengine=.To verify the engine actually ran: read
result.engineon the returnedEvaluateResult, orresult[0].certainty.kindto confirm the verdict shape ("boolean","probabilistic", or"possibilistic").
Variations#
- Same rule, every engine: call
fg.eval.evaluate(rule, head=rule, engine=engine)in a loop over("native", "souffle", "problog", "pyreason")to compare verdicts side by side. Native and Souffle return boolean rows, ProbLog returns probabilities, PyReason returns intervals. - Inspect a config without evaluating: pass a
ProbLogConfig,PyReasonConfig, orSemanticsProfiletofg.eval.preview_config(...)to see its lowered canonical preview before committing to a run. - Explain under a chosen engine:
fg.eval.explain(...)takes the sameengine=keyword and requires a closed head. See How to evaluate a rule and read the proof.
Note: engine_options= and registry= are not accepted on fg.eval.evaluate(...); configure semantics through config= instead.
See also: Engines and semantics for every engine name, every ProbLogConfig and PyReasonConfig field with defaults, and the certainty-per-engine table; Evaluation and explanation for fg.eval.evaluate and EvaluateResult; Errors and error codes for SDKStoreError; and About reasoning, evaluation, and evidence for why the engine is a per-call choice.