| Crates.io | oxirs-rule |
| lib.rs | oxirs-rule |
| version | 0.1.0 |
| created_at | 2025-09-30 08:33:26.816753+00 |
| updated_at | 2026-01-20 21:18:07.786092+00 |
| description | Forward/backward rule engine for RDFS, OWL, and SWRL reasoning |
| homepage | https://github.com/cool-japan/oxirs |
| repository | https://github.com/cool-japan/oxirs |
| max_upload_size | |
| id | 1860784 |
| size | 2,438,604 |
Status: Production Release (v0.1.0) - Released January 7, 2026
⨠Production Release: Production-ready with API stability guarantees and comprehensive testing.
A high-performance, comprehensive reasoning engine for Semantic Web applications, implementing forward chaining, backward chaining, RETE networks, RDFS, OWL RL, and SWRL rule processing.
Add to your Cargo.toml:
# Experimental feature
[dependencies]
oxirs-rule = "0.1.0"
use oxirs_rule::*;
// Create a new rule engine
let mut engine = RuleEngine::new();
// Add facts
engine.add_fact(atom!(
"knows",
term!("alice"),
term!("bob")
));
// Add rules
engine.add_rule(rule!(
[atom!("knows", var!("X"), var!("Y"))],
[atom!("friend", var!("X"), var!("Y"))]
));
// Perform forward chaining inference
let stats = engine.forward_chain()?;
println!("Derived {} new facts", stats.facts_derived);
// Query the knowledge base
let results = engine.query(&atom!("friend", var!("X"), var!("Y")))?;
for result in results {
println!("Friend relationship: {:?}", result);
}
RuleEngine - Main interface unifying all reasoning strategiesForwardChainEngine - Data-driven inference with fixpoint calculationBackwardChainEngine - Goal-driven proof search with memoizationReteNetwork - High-performance pattern matching networkRdfsReasoner - RDFS schema reasoning and entailmentOwlReasoner - OWL RL profile reasoningSwrlEngine - SWRL rule processing with built-in functions// Core data types
pub struct Rule {
pub head: Vec<RuleAtom>,
pub body: Vec<RuleAtom>,
}
pub struct RuleAtom {
pub predicate: String,
pub terms: Vec<Term>,
}
pub enum Term {
Variable(String),
Constant(String),
Literal(String),
}
Ideal for:
let stats = engine.forward_chain()?;
println!("Facts derived: {}", stats.facts_derived);
println!("Rules fired: {}", stats.rules_fired);
Ideal for:
let goal = atom!("ancestor", term!("alice"), var!("X"));
let proofs = engine.backward_chain(&goal)?;
for proof in proofs {
println!("Proof path: {:?}", proof.derivation_path);
}
Ideal for:
let mut rete = ReteNetwork::new();
rete.add_rule(&rule);
rete.add_fact(&fact);
let results = rete.execute()?;
equal(?x, ?y) - Equality testingnotEqual(?x, ?y) - Inequality testinglessThan(?x, ?y) - Numeric comparisongreaterThan(?x, ?y) - Numeric comparisonadd(?x, ?y, ?result) - Additionsubtract(?x, ?y, ?result) - Subtractionmultiply(?x, ?y, ?result) - MultiplicationstringConcat(?s1, ?s2, ?result) - String concatenationstringLength(?string, ?length) - String lengthbound(?var) - Variable binding checkunbound(?var) - Variable unbound checkAutomatic inference of:
rdfs:subClassOf)rdfs:subPropertyOf)rdfs:domain, rdfs:range)rdf:type)let mut rdfs = RdfsReasoner::new();
rdfs.add_schema_triple("Person", "rdfs:subClassOf", "Agent");
rdfs.add_data_triple("alice", "rdf:type", "Person");
let inferred = rdfs.materialize()?;
// Automatically infers: alice rdf:type Agent
Support for:
owl:sameAs, owl:differentFrom)let mut owl = OwlReasoner::new();
owl.add_axiom("hasParent", "rdf:type", "owl:TransitiveProperty");
owl.add_fact("alice", "hasParent", "bob");
owl.add_fact("bob", "hasParent", "charlie");
let inferred = owl.reason()?;
// Automatically infers: alice hasParent charlie
Support for complex rule definitions:
// Person(?p) ā§ hasAge(?p, ?age) ā§ greaterThan(?age, 18) ā Adult(?p)
let swrl_rule = SwrlRule {
body: vec![
SwrlAtom::Class("Person".to_string(), SwrlArgument::Variable("p".to_string())),
SwrlAtom::DataProperty("hasAge".to_string(),
SwrlArgument::Variable("p".to_string()),
SwrlArgument::Variable("age".to_string())),
SwrlAtom::BuiltIn("greaterThan".to_string(), vec![
SwrlArgument::Variable("age".to_string()),
SwrlArgument::Literal("18".to_string())
])
],
head: vec![
SwrlAtom::Class("Adult".to_string(), SwrlArgument::Variable("p".to_string()))
]
};
use oxirs_core::model::{Triple, IRI};
use oxirs_rule::RuleEngine;
let mut engine = RuleEngine::new();
// Convert oxirs-core triples to rule facts
engine.add_triple(&triple)?;
// Use reasoning results in SPARQL queries
let inferred_facts = engine.get_materialized_facts();
// Add to SPARQL dataset for querying
Run the comprehensive test suite:
# Run all tests
cargo nextest run --no-fail-fast
# Run specific reasoning tests
cargo nextest run -p oxirs-rule --no-fail-fast
# Run performance benchmarks
cargo test --release --features benchmarks
use oxirs_rule::config::EngineConfig;
let config = EngineConfig {
max_iterations: 1000,
cache_size: 10000,
enable_statistics: true,
reasoning_strategy: ReasoningStrategy::Hybrid,
};
let engine = RuleEngine::with_config(config);
Comprehensive error types with detailed context:
use oxirs_rule::error::RuleEngineError;
match engine.forward_chain() {
Ok(stats) => println!("Success: {} facts derived", stats.facts_derived),
Err(RuleEngineError::UnificationError(msg)) => {
eprintln!("Unification failed: {}", msg);
},
Err(RuleEngineError::CycleDetected(path)) => {
eprintln!("Infinite recursion detected: {:?}", path);
},
Err(e) => eprintln!("Other error: {}", e),
}
Built-in tracing support:
use tracing::{info, debug};
// Enable tracing
tracing_subscriber::init();
// Reasoning operations automatically logged
let stats = engine.forward_chain()?;
// Logs: "Forward chaining completed: 1000 facts derived, 50 rules fired"
cargo clippy and cargo fmtLicensed under the Apache License, Version 2.0 or the MIT License, at your option.
š Production Release (v0.1.0) ā January 7, 2026
Highlights: