1use anyhow::Result;
60
61pub mod active_learning;
62pub mod adaptive_strategies;
63pub mod advanced_integration_example;
64pub mod asp;
65pub mod backward;
66pub mod benchmark_suite;
67pub mod cache;
68pub mod chr;
69pub mod composition;
70pub mod comprehensive_tutorial;
71pub mod conflict;
72pub mod coverage;
73pub mod datalog_engine;
74pub mod debug;
75pub mod dempster_shafer;
76pub mod description_logic;
77pub mod distributed;
78pub mod entailment;
79pub mod explainable_generation;
80pub mod explanation;
81pub mod forward;
82pub mod fuzzy;
83pub mod getting_started;
84pub mod gpu_matching;
85pub mod hermit_reasoner;
86pub mod incremental;
87pub mod integration;
88pub mod integration_benchmarks;
89pub mod language;
90pub mod lazy_materialization;
91pub mod lockfree;
92pub mod materialization;
93pub mod migration;
94pub mod negation;
95pub mod optimization;
96pub mod owl;
97pub mod owl2;
98pub mod owl_dl;
99pub mod owl_el;
100pub mod owl_el_axioms;
101pub mod owl_el_reasoner;
102pub mod owl_el_tests;
103pub mod owl_profiles;
104pub mod owl_ql;
105pub mod owl_rl;
106pub mod owl_rl_reasoner;
107pub mod owl_rl_rules;
108#[cfg(test)]
109pub mod owl_rl_tests;
110pub use owl_ql::{Owl2QLTBox, QueryAtom, QueryRewriter, RewrittenQuery};
111pub mod datalog;
112pub mod n3logic;
113pub mod parallel;
114pub mod pellet_classifier;
115pub mod performance;
116pub mod possibilistic;
117pub mod probabilistic;
118pub mod probabilistic_rdf;
119pub mod problog;
120pub mod problog_inference;
121pub mod problog_solver;
122mod problog_tests;
123pub mod problog_types;
124pub mod production_utils;
125pub mod profiler;
126pub mod quantum_optimizer;
127pub mod rdf_integration;
128pub mod rdf_processing_simple;
129pub mod rdfs;
130pub mod rete;
131pub mod rete_enhanced;
132pub mod rif;
133pub mod rule_compression;
134pub mod rule_index;
135pub mod rule_index_store;
136#[cfg(test)]
137pub mod rule_index_tests;
138pub mod rule_index_types;
139pub mod rule_learning;
140pub mod rule_refinement;
141pub mod shacl_integration;
142pub mod simd_ops;
143pub mod skos;
144pub mod skos_inference;
145pub mod skos_mappings;
146pub mod skos_reasoner;
147#[cfg(test)]
148mod skos_tests;
149pub mod skos_types;
150pub mod skos_validation;
151pub mod sparql_integration;
152pub mod statistical_relational;
153pub mod swrl;
154pub mod tabling;
155pub mod temporal;
156pub mod test_generator;
157pub mod transaction;
158pub mod transfer_learning;
159pub mod uncertainty_propagation;
160
161#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
163pub struct Rule {
164 pub name: String,
165 pub body: Vec<RuleAtom>,
166 pub head: Vec<RuleAtom>,
167}
168
169#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
171pub enum RuleAtom {
172 Triple {
173 subject: Term,
174 predicate: Term,
175 object: Term,
176 },
177 Builtin {
178 name: String,
179 args: Vec<Term>,
180 },
181 NotEqual {
182 left: Term,
183 right: Term,
184 },
185 GreaterThan {
186 left: Term,
187 right: Term,
188 },
189 LessThan {
190 left: Term,
191 right: Term,
192 },
193}
194
195#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
197pub enum Term {
198 Variable(String),
199 Constant(String),
200 Literal(String),
201 Function { name: String, args: Vec<Term> },
202}
203
204#[derive(Debug)]
206pub struct RuleEngine {
207 rules: Vec<Rule>,
208 forward_chainer: forward::ForwardChainer,
209 backward_chainer: backward::BackwardChainer,
210 rete_network: rete::ReteNetwork,
211 cache: Option<crate::cache::RuleCache>,
212}
213
214impl RuleEngine {
215 pub fn new() -> Self {
216 Self {
217 rules: Vec::new(),
218 forward_chainer: forward::ForwardChainer::new(),
219 backward_chainer: backward::BackwardChainer::new(),
220 rete_network: rete::ReteNetwork::new(),
221 cache: Some(crate::cache::RuleCache::new()),
222 }
223 }
224
225 pub fn add_rule(&mut self, rule: Rule) {
227 self.rules.push(rule.clone());
228 self.forward_chainer.add_rule(rule.clone());
229 self.backward_chainer.add_rule(rule.clone());
230 if let Err(e) = self.rete_network.add_rule(&rule) {
231 tracing::warn!(
237 "RETE network rejected rule '{}': {}; rete_forward_chain results may \
238 differ from forward_chain/backward_chain for this rule",
239 rule.name,
240 e
241 );
242 }
243 }
244
245 pub fn add_rules(&mut self, rules: Vec<Rule>) {
247 for rule in rules {
248 self.add_rule(rule);
249 }
250 }
251
252 pub fn add_facts(&mut self, facts: Vec<RuleAtom>) {
254 self.forward_chainer.add_facts(facts.clone());
255 self.backward_chainer.add_facts(facts);
256 }
257
258 pub fn forward_chain(&mut self, facts: &[RuleAtom]) -> Result<Vec<RuleAtom>> {
260 self.forward_chainer.add_facts(facts.to_vec());
261 self.forward_chainer.infer()
262 }
263
264 pub fn backward_chain(&mut self, goal: &RuleAtom) -> Result<bool> {
266 self.backward_chainer.prove(goal)
267 }
268
269 pub fn rete_forward_chain(&mut self, facts: Vec<RuleAtom>) -> Result<Vec<RuleAtom>> {
271 self.rete_network.forward_chain(facts)
272 }
273
274 pub fn get_facts(&self) -> Vec<RuleAtom> {
276 self.forward_chainer.get_facts()
277 }
278
279 pub fn clear(&mut self) {
281 self.forward_chainer.clear_facts();
282 self.backward_chainer.clear_facts();
283 self.rete_network.clear();
284 self.clear_cache();
285 }
286
287 pub fn set_backward_chain_max_depth(&mut self, max_depth: usize) {
293 self.backward_chainer = backward::BackwardChainer::with_config(max_depth, false);
294 for rule in &self.rules {
296 self.backward_chainer.add_rule(rule.clone());
297 }
298 }
299
300 pub fn add_fact(&mut self, fact: RuleAtom) {
302 self.add_facts(vec![fact]);
303 }
304
305 pub fn set_cache(&mut self, cache: Option<crate::cache::RuleCache>) {
311 self.cache = cache;
312 tracing::debug!(
313 "Rule engine cache {}",
314 if self.cache.is_some() {
315 "enabled"
316 } else {
317 "disabled"
318 }
319 );
320 }
321
322 pub fn get_cache(&self) -> Option<&crate::cache::RuleCache> {
327 self.cache.as_ref()
328 }
329
330 pub fn get_cache_mut(&mut self) -> Option<&mut crate::cache::RuleCache> {
335 self.cache.as_mut()
336 }
337
338 pub fn enable_cache(&mut self) {
342 self.cache = Some(crate::cache::RuleCache::new());
343 tracing::info!("Rule engine cache enabled with default settings");
344 }
345
346 pub fn disable_cache(&mut self) {
350 self.cache = None;
351 tracing::info!("Rule engine cache disabled");
352 }
353
354 pub fn is_cache_enabled(&self) -> bool {
356 self.cache.is_some()
357 }
358
359 pub fn clear_cache(&mut self) {
363 if let Some(cache) = &self.cache {
364 cache.clear_all();
365 tracing::debug!("Rule engine cache cleared");
366 }
367 }
368
369 pub fn get_cache_statistics(&self) -> Option<crate::cache::CachingStatistics> {
373 self.cache.as_ref().map(|cache| cache.get_statistics())
374 }
375
376 pub fn warm_cache(&self, common_facts: &[RuleAtom]) {
381 if let Some(cache) = &self.cache {
382 cache.warm_cache(&self.rules, common_facts);
383 tracing::info!(
384 "Cache warmed up with {} rules and {} facts",
385 self.rules.len(),
386 common_facts.len()
387 );
388 }
389 }
390}
391
392impl Default for RuleEngine {
393 fn default() -> Self {
394 Self::new()
395 }
396}
397
398pub mod rdfs_entailment;
400
401pub mod forward_chainer;
403
404pub mod rule_parser;
406
407pub mod rete_network;
409
410pub mod conflict_resolver;
412
413pub mod backward_chainer;
415
416pub mod rule_graph;
418
419pub mod rule_compiler;
421
422pub mod truth_maintenance;
424
425pub mod rule_tracer;
427
428pub mod rule_serializer;
430
431pub mod rule_validator;
433
434pub mod rule_executor;
436
437pub mod rule_statistics;
439
440pub mod jena_rl;
442pub use jena_rl::{parse_and_lower, parse_jrl, JrlParseError, JrlRuleSet, LoweringError};
443
444pub mod manchester;
446pub use manchester::{
447 emit as manchester_emit, parse as manchester_parse, ManchesterError, ManchesterExpr,
448};
449
450#[cfg(test)]
451mod comprehensive_tests;
452#[cfg(test)]
453mod comprehensive_tests_extended;