mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-30 04:40:16 +00:00
- 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
179 lines
4.7 KiB
Markdown
179 lines
4.7 KiB
Markdown
# Reasoning
|
|
|
|
> **Simplified reasoning module supporting rule-based inference, SPARQL, and high-performance pattern matching.**
|
|
|
|
---
|
|
|
|
## 🎯 Overview
|
|
|
|
<div class="grid cards" markdown>
|
|
|
|
- :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
|
|
|
|
</div>
|
|
|
|
!!! 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
|
|
|
|
```python
|
|
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)
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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
|
|
|
|
- [Ontology Module](ontology.md) - Source of schema-based rules
|
|
- [Triplet Store Module](triplet_store.md) - Backend for SPARQL reasoning
|
|
- [Modules Guide](../modules.md#quality-assurance) - Consistency checking overview
|