## Chase-rs An implementation of the chase algorithm in Rust for advanced reasoning engines. ### Overview The chase algorithm is a fundamental technique in context of database theory and knowledge representation used for: - Query answering under tuple-generating dependencies (TGDs) - Computing universal models - Ontology-based data access (OBDA) - Datalog with existential rules This implementation provides a **restricted chase** that guarantees termination even with existential rules by tracking applied triggers. ### Features - **Core Data Types**: Terms, Atoms, Rules, and Instances - **Existential Quantification**: Automatic generation of labeled nulls - **Restricted Chase**: Termination guarantees via trigger tracking - **Fluent API**: `RuleBuilder` for readable rule construction - **Zero Dependencies**: Pure Rust with no external runtime dependencies See [ROADMAP.md](ROADMAP.md) for the list of implemented and planned features. > [!IMPORTANT] > This project is still in early development, so bugs and breaking changes are expected. > Please use the [issues page](https://code.obsidian.systems/habedi-work/chase-rs/issues) to report bugs or request features. --- ### Quickstart ```rust use chase_rs::{chase, Atom, Instance, Term}; use chase_rs::chase::rule::RuleBuilder; // Create initial facts let instance: Instance = vec![ Atom::new("Parent", vec![Term::constant("alice"), Term::constant("bob")]), Atom::new("Parent", vec![Term::constant("bob"), Term::constant("carol")]), ].into_iter().collect(); // Define rules // Parent(X, Y) -> Ancestor(X, Y) let rule1 = RuleBuilder::new() .when("Parent", vec![Term::var("X"), Term::var("Y")]) .then("Ancestor", vec![Term::var("X"), Term::var("Y")]) .build(); // Ancestor(X, Y), Parent(Y, Z) -> Ancestor(X, Z) let rule2 = RuleBuilder::new() .when("Ancestor", vec![Term::var("X"), Term::var("Y")]) .when("Parent", vec![Term::var("Y"), Term::var("Z")]) .then("Ancestor", vec![Term::var("X"), Term::var("Z")]) .build(); // Run the chase let result = chase(instance, &[rule1, rule2]); assert!(result.terminated); println!("Derived {} facts", result.instance.len()); ``` ### Existential Rules Rules with head-only variables (existential quantification) automatically generate fresh labeled nulls: ```rust // Every person has an SSN: Person(X) -> HasSSN(X, Y) let rule = RuleBuilder::new() .when("Person", vec![Term::var("X")]) .then("HasSSN", vec![Term::var("X"), Term::var("Y")]) // Y is existential .build(); ``` ### Usful Commands ```bash # Run all tests make test # Run linter checks make lint # Run with optimizations make build # Run CLI make run ``` ### License This project is licensed under [BSD-3](LICENSE).