Diagrams (docs/assets/img/diagrams/): - architecture-overview.svg: 4-column layered architecture - pipeline-flow.svg: 8-step numbered pipeline flow - kg-structure.svg: entity/relation graph with typed nodes and labeled edges - graphrag-flow.svg: dual-path retrieval (vector + graph) to LLM to grounded answer - extraction-pipeline.svg: NER/Relation/Coreference fan-out to Triplet Generator - agent-context-flow.svg: AgentContext hub with VectorStore and ContextGraph - reasoning-chain.svg: forward-chaining inference with explanation path Wordmark logo (light + dark SVG variants): - Green rounded-square S icon + Semantica text in green - docs.json updated to use wordmark SVGs for light and dark modes Pages updated with diagrams: - index.md, architecture.md, quickstart.md, concepts.md - reference/kg.md, reference/pipeline.md, reference/semantic_extract.md - reference/context.md, reference/reasoning.md
7.2 KiB
title, description, icon
| title | description | icon |
|---|---|---|
| Reasoning Module | Forward chaining, Rete, deductive, abductive, SPARQL, Datalog, and temporal reasoning with explainable inference paths. | microchip |
semantica.reasoning derives new knowledge from existing facts using logical rules. Every engine produces explainable inference paths — traceable chains of rules and facts, not black-box conclusions.
What You Get
Reasoner— main facade for IF/THEN forward-chaining with variable substitutionGraphReasoner— inference over full knowledge graph structure (transitivity, symmetry, inverses)ReteEngine— high-performance pattern matching via the Rete algorithm for large rule setsSPARQLReasoner— query expansion and property chain inference over RDF graphsDatalogReasoner— recursive Horn clause rules with guaranteed fixpoint termination (v0.4.0)TemporalReasoningEngine— all 13 Allen interval algebra relations for time-aware inferenceExplanationGenerator— structured explanation paths for every derived conclusion
<img src="/assets/img/diagrams/reasoning-chain.svg" alt="Forward chaining inference: known facts + IF/THEN rules produce derived facts with a full traceable explanation path" style={{ width: '100%', borderRadius: '12px', margin: '0 0 24px' }} />
Reasoner (Main Facade)
The unified entry point for rule-based forward-chaining inference:
from semantica.reasoning import Reasoner, Rule, Fact, RuleType
reasoner = Reasoner()
# Add base facts
reasoner.add_fact(Fact(subject="John", predicate="is_a", obj="Manager"))
reasoner.add_fact(Fact(subject="John", predicate="is_a", obj="Employee"))
# Add an IF/THEN rule
reasoner.add_rule(Rule(
rule_type=RuleType.FORWARD_CHAIN,
conditions=[
{"subject": "?x", "predicate": "is_a", "object": "Manager"}
],
conclusion={"subject": "?x", "predicate": "has_authority", "object": "true"}
))
# Run inference
result = reasoner.infer()
for inference in result.derived_facts:
print(f"{inference.subject} {inference.predicate} {inference.obj}")
print(f" Derived via: {inference.explanation}")
Built-In Rule Templates
engine = Reasoner()
# Transitive closure: A→B, B→C ⟹ A→C
engine.apply_transitivity("located_in")
# Symmetry: A knows B ⟹ B knows A
engine.apply_symmetry("knows")
# Inverse: A parent_of B ⟹ B child_of A
engine.apply_inverse("parent_of", "child_of")
GraphReasoner
Inference over the full knowledge graph structure:
from semantica.reasoning import GraphReasoner
graph_reasoner = GraphReasoner(kg)
# Define a transitive ancestor rule
graph_reasoner.add_rule({
"if": [
{"subject": "?a", "predicate": "parent_of", "object": "?b"},
{"subject": "?b", "predicate": "parent_of", "object": "?c"}
],
"then": {"subject": "?a", "predicate": "ancestor_of", "object": "?c"}
})
inferences = graph_reasoner.infer(kg)
for inf in inferences:
print(f"{inf['subject']} {inf['predicate']} {inf['object']}")
ReteEngine
High-performance pattern matching using the Rete algorithm — far faster than naive forward chaining for large rule sets because it caches partial matches across iterations:
from semantica.reasoning import ReteEngine
engine = ReteEngine()
engine.load_rules("rules/domain_rules.json")
results = engine.run(kg)
# Inspect the Rete network
root = engine.get_root()
alpha_nodes = engine.get_alpha_nodes() # single-condition filters
beta_nodes = engine.get_beta_nodes() # join nodes
Rule format (JSON):
{
"rules": [
{
"name": "manager_authority",
"conditions": [
{ "subject": "?x", "predicate": "role", "object": "Manager" }
],
"action": { "subject": "?x", "predicate": "has_authority", "object": "true" }
}
]
}
SPARQLReasoner
Query-based inference over RDF graphs with property chain support:
from semantica.reasoning import SPARQLReasoner
reasoner = SPARQLReasoner(graph=rdf_graph)
result = reasoner.query("""
PREFIX ex: <http://example.org/>
SELECT ?person ?company WHERE {
?person ex:founded ?company .
?company ex:located_in ex:SiliconValley .
}
""")
for row in result.bindings:
print(row["person"], row["company"])
# Property chain inference: A knows B, B colleague_of C ⟹ A knows C
reasoner.add_property_chain("knows", ["knows", "colleague_of"])
inferences = reasoner.infer_property_chains()
DatalogReasoner (v0.4.0)
Pure-Python bottom-up semi-naive fixpoint evaluation for recursive Horn clause rules. Termination is guaranteed — the engine detects fixpoint convergence and stops:
from semantica.reasoning import DatalogReasoner, DatalogFact, DatalogRule
datalog = DatalogReasoner()
# Base facts
datalog.add_fact(DatalogFact("parent", ("alice", "bob")))
datalog.add_fact(DatalogFact("parent", ("bob", "charlie")))
# Recursive rules (Horn clauses)
datalog.add_rule(DatalogRule("ancestor(?X, ?Y) :- parent(?X, ?Y)."))
datalog.add_rule(DatalogRule("ancestor(?X, ?Z) :- parent(?X, ?Y), ancestor(?Y, ?Z)."))
# Evaluate to fixpoint
datalog.evaluate()
# Query
results = datalog.query("ancestor(alice, ?Z)")
# → [{"Z": "bob"}, {"Z": "charlie"}]
TemporalReasoningEngine
Reason about time intervals using all 13 Allen interval algebra relations:
from semantica.reasoning import TemporalReasoningEngine, TemporalInterval, IntervalRelation
engine = TemporalReasoningEngine()
ceo_tenure = TemporalInterval(start="1997-09-16", end="2011-08-24")
board_member = TemporalInterval(start="2000-01-01", end="2012-06-01")
relation = engine.get_relation(ceo_tenure, board_member)
# → IntervalRelation.DURING (ceo_tenure is fully inside board_member)
All 13 Allen interval algebra relations are supported:
| Relation | Meaning |
|---|---|
BEFORE |
A ends before B starts |
MEETS |
A ends exactly when B starts |
OVERLAPS |
A starts before B, ends inside B |
DURING |
A is fully inside B |
STARTS |
A and B start together, A ends first |
FINISHES |
A and B end together, A starts later |
EQUALS |
Identical intervals |
| + 6 inverses | AFTER, MET_BY, OVERLAPPED_BY, CONTAINS, STARTED_BY, FINISHED_BY |
ExplanationGenerator
Generate structured step-by-step explanations for any derived conclusion:
from semantica.reasoning import ExplanationGenerator
generator = ExplanationGenerator(reasoner)
explanation = generator.explain(
conclusion={"subject": "John", "predicate": "has_authority", "object": "true"}
)
print(explanation.conclusion)
print(f"Confidence: {explanation.confidence:.2f}")
for step in explanation.reasoning_path.steps:
print(f" Step {step.depth}: {step.fact}")
print(f" via rule: '{step.rule_name}'")