Files
semantica/docs/reference/reasoning.md
T
KaifAhmad1 eaa1fbefa6 feat(reasoning): add dedicated reasoning tests and fix critical reasoning bugs
- 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
2025-12-23 21:26:26 +05:30

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

  1. Limit Recursion: Be careful with recursive rules (e.g., A(x,y) -> A(y,x)) which can cause infinite loops in naive implementations.
  2. Use Rete for Scale: For >100 rules or >10k facts, always use the Rete engine.
  3. Materialize vs. Query: Materialize (pre-compute) for read-heavy workloads; Query-rewrite for write-heavy workloads.
  4. Validate Rules: Ensure rules are logically consistent to avoid exploding the fact space.

See Also