Hassan Abedi c53cc11e5f WIP
2026-03-09 10:42:36 +01:00
WIP
2026-03-09 10:42:36 +01:00
WIP
2026-03-09 10:42:36 +01:00
WIP
2026-03-09 10:42:36 +01:00
2026-03-09 10:42:31 +01:00
WIP
2026-03-09 10:42:36 +01:00
WIP
2026-03-09 10:42:36 +01:00
WIP
2026-03-09 10:42:36 +01:00
WIP
2026-03-09 10:42:36 +01:00
2026-03-09 10:42:31 +01:00
WIP
2026-03-09 10:42:36 +01:00
2026-03-09 10:42:31 +01:00
WIP
2026-03-09 10:42:36 +01:00
2026-03-09 10:42:31 +01:00

chase-rs

An efficient implementation of the chase algorithm in Rust for advanced reasoning engines.

Overview

The chase algorithm is a fundamental technique in 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 ensures termination even with existential rules by tracking applied triggers.

Features

  • Core Data Types: Terms, Atoms, Rules, 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

Quick Start

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:

// 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();

Project Structure

src/
├── lib.rs              # Library root and re-exports
├── main.rs             # Binary entry point
└── chase/
    ├── mod.rs          # Module exports
    ├── term.rs         # Terms: Constants, Nulls, Variables
    ├── atom.rs         # Atoms: Predicate(term1, term2, ...)
    ├── instance.rs     # Database instance (set of facts)
    ├── rule.rs         # TGDs with RuleBuilder
    ├── substitution.rs # Variable bindings and unification
    └── engine.rs       # Core chase algorithm
tests/
├── integration_tests.rs
├── regression_tests.rs
└── property_tests.rs

Building and Testing

# Run all tests
cargo test

# Run with optimizations
cargo build --release

# Check for lint warnings
cargo clippy

License

This project is licensed under BSD-3.

Description
A chase algorithm implementation in Rust 🦀
Readme BSD-3-Clause 133 KiB
Languages
Rust 92%
Makefile 5.5%
Nix 2.5%