use anyhow::Result;
use oxirs_rule::*;
fn main() -> Result<()> {
println!("🌟 Welcome to OxiRS Rule Engine!");
println!("=================================\n");
step1_create_engine()?;
step2_add_rules()?;
step3_inference()?;
step4_querying()?;
println!("🎉 Congratulations! You've completed the getting started guide.");
println!("Next steps:");
println!(" - Try the comprehensive_tutorial example");
println!(" - Explore RDFS, OWL, and SWRL reasoning");
println!(" - Use debugging tools for complex scenarios");
Ok(())
}
fn step1_create_engine() -> Result<()> {
println!("📖 Step 1: Creating a Rule Engine");
println!("--------------------------------");
let _engine = RuleEngine::new();
println!("✅ Created a new rule engine!");
println!(" The engine supports:");
println!(" - Forward chaining (derive new facts from rules)");
println!(" - Backward chaining (prove goals by finding supporting facts)");
println!(" - RETE network (efficient pattern matching)");
println!();
Ok(())
}
fn step2_add_rules() -> Result<()> {
println!("📖 Step 2: Adding Rules");
println!("----------------------");
let mut engine = RuleEngine::new();
let cat_rule = Rule {
name: "cats_are_animals".to_string(),
body: vec![
RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("cat".to_string()),
},
],
head: vec![
RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("animal".to_string()),
},
],
};
engine.add_rule(cat_rule);
println!("✅ Added rule: cats_are_animals");
println!(" If ?X type cat → ?X type animal");
let animal_rule = Rule {
name: "animals_are_alive".to_string(),
body: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("animal".to_string()),
}],
head: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("property".to_string()),
object: Term::Constant("alive".to_string()),
}],
};
engine.add_rule(animal_rule);
println!("✅ Added rule: animals_are_alive");
println!(" If ?X type animal → ?X property alive");
println!();
Ok(())
}
fn step3_inference() -> Result<()> {
println!("📖 Step 3: Adding Facts and Running Inference");
println!("---------------------------------------------");
let mut engine = RuleEngine::new();
engine.add_rule(Rule {
name: "cats_are_animals".to_string(),
body: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("cat".to_string()),
}],
head: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("animal".to_string()),
}],
});
engine.add_rule(Rule {
name: "animals_are_alive".to_string(),
body: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("animal".to_string()),
}],
head: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("property".to_string()),
object: Term::Constant("alive".to_string()),
}],
});
let facts = vec![
RuleAtom::Triple {
subject: Term::Constant("whiskers".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("cat".to_string()),
},
RuleAtom::Triple {
subject: Term::Constant("fluffy".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("cat".to_string()),
},
];
println!("📝 Initial facts:");
for fact in &facts {
if let RuleAtom::Triple {
subject,
predicate,
object,
} = fact
{
if let (Term::Constant(s), Term::Constant(p), Term::Constant(o)) =
(subject, predicate, object)
{
println!(" {s} {p} {o}");
}
}
}
println!("\n🔄 Running forward chaining...");
let results = engine.forward_chain(&facts)?;
println!("\n🧠 Derived facts:");
for result in &results {
if let RuleAtom::Triple {
subject,
predicate,
object,
} = result
{
if let (Term::Constant(s), Term::Constant(p), Term::Constant(o)) =
(subject, predicate, object)
{
if !facts.contains(result) {
println!(" {s} {p} {o} (derived)");
}
}
}
}
println!("\n💡 What happened?");
println!(" 1. We started with: whiskers type cat, fluffy type cat");
println!(" 2. Rule 1 derived: whiskers type animal, fluffy type animal");
println!(" 3. Rule 2 derived: whiskers property alive, fluffy property alive");
println!();
Ok(())
}
fn step4_querying() -> Result<()> {
println!("📖 Step 4: Querying the Knowledge Base");
println!("-------------------------------------");
let mut engine = RuleEngine::new();
engine.add_rule(Rule {
name: "cats_are_animals".to_string(),
body: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("cat".to_string()),
}],
head: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("animal".to_string()),
}],
});
engine.add_rule(Rule {
name: "animals_are_alive".to_string(),
body: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("animal".to_string()),
}],
head: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("property".to_string()),
object: Term::Constant("alive".to_string()),
}],
});
let facts = vec![RuleAtom::Triple {
subject: Term::Constant("whiskers".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("cat".to_string()),
}];
engine.add_facts(facts);
println!("🔍 Asking questions using backward chaining:");
let query1 = RuleAtom::Triple {
subject: Term::Constant("whiskers".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("animal".to_string()),
};
let answer1 = engine.backward_chain(&query1)?;
println!(" Q: Is whiskers an animal?");
println!(" A: {} ✅", if answer1 { "Yes" } else { "No" });
let query2 = RuleAtom::Triple {
subject: Term::Constant("whiskers".to_string()),
predicate: Term::Constant("property".to_string()),
object: Term::Constant("alive".to_string()),
};
let answer2 = engine.backward_chain(&query2)?;
println!(" Q: Is whiskers alive?");
println!(" A: {} ✅", if answer2 { "Yes" } else { "No" });
let query3 = RuleAtom::Triple {
subject: Term::Constant("whiskers".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("dog".to_string()),
};
let answer3 = engine.backward_chain(&query3)?;
println!(" Q: Is whiskers a dog?");
println!(" A: {} ❌", if answer3 { "Yes" } else { "No" });
println!("\n💡 How backward chaining works:");
println!(" - To prove 'whiskers is alive', the engine:");
println!(" - Looks for rules that conclude 'X property alive'");
println!(" - Finds the rule: 'if X type animal → X property alive'");
println!(" - Now needs to prove 'whiskers type animal'");
println!(" - Finds the rule: 'if X type cat → X type animal'");
println!(" - Checks if 'whiskers type cat' is a known fact");
println!(" - Since it is, the proof succeeds!");
println!();
Ok(())
}
#[allow(dead_code)]
fn bonus_patterns() -> Result<()> {
println!("🎯 Bonus: Common Patterns and Best Practices");
println!("===========================================");
let mut engine = RuleEngine::new();
let conditional_rule = Rule {
name: "smart_adult_rule".to_string(),
body: vec![
RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("type".to_string()),
object: Term::Constant("person".to_string()),
},
RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("age".to_string()),
object: Term::Variable("A".to_string()),
},
RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("iq".to_string()),
object: Term::Variable("I".to_string()),
},
],
head: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("category".to_string()),
object: Term::Constant("qualified_candidate".to_string()),
}],
};
engine.add_rule(conditional_rule);
let transitive_rule = Rule {
name: "transitivity".to_string(),
body: vec![
RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("manages".to_string()),
object: Term::Variable("Y".to_string()),
},
RuleAtom::Triple {
subject: Term::Variable("Y".to_string()),
predicate: Term::Constant("manages".to_string()),
object: Term::Variable("Z".to_string()),
},
],
head: vec![RuleAtom::Triple {
subject: Term::Variable("X".to_string()),
predicate: Term::Constant("indirectly_manages".to_string()),
object: Term::Variable("Z".to_string()),
}],
};
engine.add_rule(transitive_rule);
println!("✅ Added common rule patterns:");
println!(" - Conditional rules (multiple body conditions)");
println!(" - Transitive rules (chain relationships)");
println!("\n📚 Best Practices:");
println!(" 1. Use descriptive rule names");
println!(" 2. Group related rules together");
println!(" 3. Test with small datasets first");
println!(" 4. Use debugging tools for complex scenarios");
println!(" 5. Consider performance for large datasets");
println!(" 6. Validate rule logic before deployment");
Ok(())
}