- Added tests/reasoning/ directory with unit and integration tests - Fixed indentation bug in Reasoner.add_fact for dictionary-based relationships - Fixed regex variable matching in Reasoner._match_pattern - Fixed variable handling in SPARQLReasoner query expansion - Cleaned up cookbook and documentation references
4.7 KiB
Reasoning
Simplified reasoning module supporting rule-based inference, SPARQL, and high-performance pattern matching.
🎯 Overview
-
:material-brain:{ .lg .middle } Rule-based Inference
Forward-chaining inference engine with variable substitution
-
:material-database-search:{ .lg .middle } SPARQL Reasoning
Query expansion and property chain inference for RDF graphs
-
:material-flash:{ .lg .middle } Rete Algorithm
High-performance pattern matching for large rule sets
-
:material-text-box-search:{ .lg .middle } Explanation
Generate natural language explanations for inferred facts
!!! tip "When to Use"
- Inference: Deriving new facts from existing data (e.g., Parent(A,B) & Parent(B,C) -> Grandparent(A,C))
- Query Expansion: Finding results that aren't explicitly stored but implied
- Explanation: Understanding the reasoning path for any derived fact
- Validation: Checking logical consistency of the knowledge graph
⚙️ Algorithms Used
Forward Chaining
- Variable Substitution: Supports patterns like
Person(?x)to match facts and bind variables. - Recursive Inference: Continues deriving facts until no new information can be found.
- Priority-based Execution: Rules can be prioritized to control the inference flow.
Rete Algorithm
- Alpha Nodes: Filter facts by single attributes (e.g.,
type=Person). - Beta Nodes: Join results from Alpha nodes (e.g.,
Person.id == Parent.child_id). - Memory: Stores partial matches to avoid re-computation.
- Efficiency: Optimal for scenarios with many rules and frequent fact updates.
Main Classes
Reasoner (Facade)
The high-level interface for the reasoning module.
Methods:
| Method | Description |
|---|---|
infer_facts(facts, rules) |
Derive new facts from initial state |
backward_chain(goal) |
Prove a goal using backward chaining |
add_rule(rule) |
Add a new inference rule |
add_fact(fact) |
Add a fact to working memory |
clear() |
Reset the reasoner state |
ReteEngine
High-performance pattern matching engine.
Methods:
| Method | Description |
|---|---|
build_network(rules) |
Compile rules into a Rete network |
add_fact(fact) |
Propagate fact through the network |
match_patterns() |
Get triggered rules |
ExplanationGenerator
Explains why a fact was inferred.
Methods:
| Method | Description |
|---|---|
generate_explanation(result) |
Generate reasoning trace for an InferenceResult |
Usage Examples
Simple Rule-based Inference
from semantica.reasoning import Reasoner
reasoner = Reasoner()
# Define rules
rules = [
"IF Person(?x) THEN Human(?x)",
"IF Human(?x) AND Parent(?x, ?y) THEN Human(?y)"
]
# Initial facts
facts = ["Person(John)", "Parent(John, Jane)"]
# Run inference
new_facts = reasoner.infer_facts(facts, rules)
# Result: ["Human(John)", "Human(Jane)"]
Goal-driven Reasoning (Backward Chaining)
from semantica.reasoning import Reasoner
reasoner = Reasoner()
reasoner.add_rule("IF Parent(?a, ?b) AND Parent(?b, ?c) THEN Grandparent(?a, ?c)")
reasoner.add_fact("Parent(Alice, Bob)")
reasoner.add_fact("Parent(Bob, Charlie)")
# Prove a goal
proof = reasoner.backward_chain("Grandparent(Alice, Charlie)")
if proof:
print(f"Proven: {proof.conclusion}")
print(f"Steps: {proof.premises}")
Knowledge Graph Enrichment
from semantica.reasoning import Reasoner, Rule
from semantica.kg import KnowledgeGraph
# 1. Define Rules
rules = [
"IF Sibling(?x, ?y) THEN Sibling(?y, ?x)",
"IF Ancestor(?x, ?y) AND Ancestor(?y, ?z) THEN Ancestor(?x, ?z)"
]
# 2. Load Graph and Run Inference
kg = KnowledgeGraph()
reasoner = Reasoner()
inferred = reasoner.infer_facts(kg.get_all_triplets(), rules)
# 3. Update Graph
for fact_str in inferred:
kg.add_fact_from_string(fact_str)
Best Practices
- Limit Recursion: Be careful with recursive rules (e.g.,
A(x,y) -> A(y,x)) which can cause infinite loops in naive implementations. - Use Rete for Scale: For >100 rules or >10k facts, always use the Rete engine.
- Materialize vs. Query: Materialize (pre-compute) for read-heavy workloads; Query-rewrite for write-heavy workloads.
- Validate Rules: Ensure rules are logically consistent to avoid exploding the fact space.
See Also
- Ontology Module - Source of schema-based rules
- Triplet Store Module - Backend for SPARQL reasoning
- Modules Guide - Consistency checking overview